Micron Document
NexusPi Git Node


Displaying Raw • Download

webconsole/index.html f0aee0671e84b627f90883c0f1fca8f0d4dbc9da (f0aee067) Text, 221.30 KB

Tff7b72<!doctype html>
Tb4b4b4<Tff7b72html Te6edf3langTff7b72=Ta5d6ff"en"Tb4b4b4>
Tb4b4b4<Tff7b72headTb4b4b4>
Tb4b4b4<Tff7b72meta Te6edf3charsetTff7b72=Ta5d6ff"utf-8"Tb4b4b4>
Tb4b4b4<Tff7b72meta Te6edf3nameTff7b72=Ta5d6ff"viewport" Te6edf3contentTff7b72=Ta5d6ff"width=device-width, initial-scale=1"Tb4b4b4>
Tb4b4b4<Tff7b72titleTb4b4b4>RNode ConsoleTb4b4b4<Tb4b4b4/Tff7b72titleTb4b4b4>
Tb4b4b4<Tff7b72styleTb4b4b4>
Tb4b4b4:Tf0883eroot Tb4b4b4{
Te6edf3--bgTb4b4b4: T79c0ff#f6f7f9Tb4b4b4;
Te6edf3--panelTb4b4b4: T79c0ff#ffffffTb4b4b4;
Te6edf3--inkTb4b4b4: T79c0ff#1d2129Tb4b4b4;
Te6edf3--mutedTb4b4b4: T79c0ff#6a737dTb4b4b4;
Te6edf3--borderTb4b4b4: T79c0ff#e1e4e8Tb4b4b4;
Te6edf3--accentTb4b4b4: T79c0ff#2563ebTb4b4b4;
Te6edf3--accent-inkTb4b4b4: T79c0ff#ffffffTb4b4b4;
Te6edf3--okTb4b4b4: T79c0ff#15803dTb4b4b4;
Te6edf3--warnTb4b4b4: T79c0ff#b45309Tb4b4b4;
Te6edf3--errTb4b4b4: T79c0ff#b91c1cTb4b4b4;
Te6edf3--hoverTb4b4b4: Tffa657rgbaTb4b4b4(T79c0ff0Tb4b4b4,T79c0ff0Tb4b4b4,T79c0ff0Tb4b4b4,T79c0ff0.04Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4@Tff7b72media Tff7b72(Tff7b72prefers-color-schemeTff7b72: Tff7b72darkTff7b72) Tb4b4b4{
Tb4b4b4:Tf0883eroot Tb4b4b4{ Te6edf3--bgTb4b4b4:T79c0ff#0f1115Tb4b4b4; Te6edf3--panelTb4b4b4:T79c0ff#161a20Tb4b4b4; Te6edf3--inkTb4b4b4:T79c0ff#e6e8ebTb4b4b4; Te6edf3--mutedTb4b4b4:T79c0ff#8b949eTb4b4b4; Te6edf3--borderTb4b4b4:T79c0ff#2a313aTb4b4b4; Te6edf3--accentTb4b4b4:T79c0ff#3b82f6Tb4b4b4; Te6edf3--hoverTb4b4b4: Tffa657rgbaTb4b4b4(T79c0ff255Tb4b4b4,T79c0ff255Tb4b4b4,T79c0ff255Tb4b4b4,T79c0ff0.05Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4}
Tff7b72* Tb4b4b4{ Tff7b72box-sizingTb4b4b4: Tff7b72border-boxTb4b4b4; Tb4b4b4}
Tff7b72htmlTff7b72, Tff7b72body Tb4b4b4{ Tff7b72heightTb4b4b4: T79c0ff100Tffa657%Tb4b4b4; Tff7b72marginTb4b4b4: T79c0ff0Tb4b4b4; Tb4b4b4}
Tff7b72body Tb4b4b4{ Tff7b72fontTb4b4b4: T79c0ff13Tffa657pxTff7b72/T79c0ff1.4 Tff7b72-Te6edf3apple-systemTb4b4b4, Te6edf3BlinkMacSystemFontTb4b4b4, Ta5d6ff"Segoe UI"Tb4b4b4, Te6edf3RobotoTb4b4b4, Tff7b72sans-serifTb4b4b4; Tff7b72backgroundTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--bgTb4b4b4)Tb4b4b4; Tff7b72colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--inkTb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4#T7ee787app Tb4b4b4{ Tff7b72displayTb4b4b4: Tff7b72flexTb4b4b4; Tff7b72flex-directionTb4b4b4: Tff7b72columnTb4b4b4; Tff7b72heightTb4b4b4: T79c0ff100Tffa657vhTb4b4b4; Tff7b72min-heightTb4b4b4: T79c0ff0Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364topbar Tb4b4b4{ Tff7b72displayTb4b4b4: Tff7b72flexTb4b4b4; Tff7b72align-itemsTb4b4b4: Tff7b72centerTb4b4b4; Tff7b72gapTb4b4b4: T79c0ff8Tffa657pxTb4b4b4; Tff7b72paddingTb4b4b4: T79c0ff8Tffa657px T79c0ff12Tffa657pxTb4b4b4; Tff7b72backgroundTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--panelTb4b4b4)Tb4b4b4; Tff7b72border-bottomTb4b4b4: T79c0ff1Tffa657px Tff7b72solid Td2a8ffvarTb4b4b4(Te6edf3--borderTb4b4b4)Tb4b4b4; Tff7b72flex-wrapTb4b4b4: Tff7b72wrapTb4b4b4; Tff7b72flexTb4b4b4: T79c0ff0 T79c0ff0 Tff7b72autoTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364topbar Tff7b72strong Tb4b4b4{ Tff7b72font-sizeTb4b4b4: T79c0ff14Tffa657pxTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364topbar Tff7b72selectTff7b72, Tb4b4b4.T56d364topbar Tff7b72inputTff7b72, Tb4b4b4.T56d364topbar Tff7b72button Tb4b4b4{ Tff7b72fontTb4b4b4: Tff7b72inheritTb4b4b4; Tff7b72paddingTb4b4b4: T79c0ff4Tffa657px T79c0ff8Tffa657pxTb4b4b4; Tff7b72borderTb4b4b4: T79c0ff1Tffa657px Tff7b72solid Td2a8ffvarTb4b4b4(Te6edf3--borderTb4b4b4)Tb4b4b4; Tff7b72border-radiusTb4b4b4: T79c0ff4Tffa657pxTb4b4b4; Tff7b72backgroundTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--panelTb4b4b4)Tb4b4b4; Tff7b72colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--inkTb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364topbar Tff7b72button Tb4b4b4{ Tff7b72cursorTb4b4b4: Tff7b72pointerTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364topbar Tff7b72buttonTb4b4b4:Tf0883edisabled Tb4b4b4{ Tff7b72opacityTb4b4b4: T79c0ff0.5Tb4b4b4; Tff7b72cursorTb4b4b4: Tff7b72not-allowedTb4b4b4; Tb4b4b4}
Tff7b72buttonTb4b4b4.T56d364primary Tb4b4b4{ Tff7b72backgroundTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--accentTb4b4b4)Tb4b4b4; Tff7b72colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--accent-inkTb4b4b4)Tb4b4b4; Tff7b72border-colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--accentTb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364spacer Tb4b4b4{ Tff7b72flexTb4b4b4: T79c0ff1Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364sep Tb4b4b4{ Tff7b72widthTb4b4b4: T79c0ff1Tffa657pxTb4b4b4; Tff7b72heightTb4b4b4: T79c0ff18Tffa657pxTb4b4b4; Tff7b72backgroundTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--borderTb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364pill Tb4b4b4{ Tff7b72paddingTb4b4b4: T79c0ff3Tffa657px T79c0ff10Tffa657pxTb4b4b4; Tff7b72border-radiusTb4b4b4: T79c0ff999Tffa657pxTb4b4b4; Tff7b72font-sizeTb4b4b4: T79c0ff12Tffa657pxTb4b4b4; Tff7b72font-weightTb4b4b4: T79c0ff500Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364st-idle Tb4b4b4{ Tff7b72backgroundTb4b4b4: Tffa657rgbaTb4b4b4(T79c0ff107Tb4b4b4,T79c0ff114Tb4b4b4,T79c0ff128Tb4b4b4,T79c0ff0.15Tb4b4b4)Tb4b4b4; Tff7b72colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--mutedTb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364st-connecting Tb4b4b4{ Tff7b72backgroundTb4b4b4: Tffa657rgbaTb4b4b4(T79c0ff180Tb4b4b4,T79c0ff131Tb4b4b4,T79c0ff9Tb4b4b4,T79c0ff0.15Tb4b4b4)Tb4b4b4; Tff7b72colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--warnTb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364st-ok Tb4b4b4{ Tff7b72backgroundTb4b4b4: Tffa657rgbaTb4b4b4(T79c0ff21Tb4b4b4,T79c0ff128Tb4b4b4,T79c0ff61Tb4b4b4,T79c0ff0.15Tb4b4b4)Tb4b4b4; Tff7b72colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--okTb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364st-err Tb4b4b4{ Tff7b72backgroundTb4b4b4: Tffa657rgbaTb4b4b4(T79c0ff185Tb4b4b4,T79c0ff28Tb4b4b4,T79c0ff28Tb4b4b4,T79c0ff0.15Tb4b4b4)Tb4b4b4; Tff7b72colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--errTb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364tabbar Tb4b4b4{ Tff7b72displayTb4b4b4: Tff7b72flexTb4b4b4; Tff7b72gapTb4b4b4: T79c0ff2Tffa657pxTb4b4b4; Tff7b72paddingTb4b4b4: T79c0ff0 T79c0ff12Tffa657pxTb4b4b4; Tff7b72backgroundTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--panelTb4b4b4)Tb4b4b4; Tff7b72border-bottomTb4b4b4: T79c0ff1Tffa657px Tff7b72solid Td2a8ffvarTb4b4b4(Te6edf3--borderTb4b4b4)Tb4b4b4; Tff7b72overflow-xTb4b4b4: Tff7b72autoTb4b4b4; Tff7b72flexTb4b4b4: T79c0ff0 T79c0ff0 Tff7b72autoTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364tab Tb4b4b4{ Tff7b72paddingTb4b4b4: T79c0ff8Tffa657px T79c0ff14Tffa657pxTb4b4b4; Tff7b72backgroundTb4b4b4: Tff7b72transparentTb4b4b4; Tff7b72borderTb4b4b4: Tff7b72noneTb4b4b4; Tff7b72border-bottomTb4b4b4: T79c0ff2Tffa657px Tff7b72solid Tff7b72transparentTb4b4b4; Tff7b72colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--mutedTb4b4b4)Tb4b4b4; Tff7b72cursorTb4b4b4: Tff7b72pointerTb4b4b4; Tff7b72fontTb4b4b4: Tff7b72inheritTb4b4b4; Tff7b72white-spaceTb4b4b4: Tff7b72nowrapTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364tabTb4b4b4:Tf0883ehoverTb4b4b4:Tf0883enotTff7b72(Tb4b4b4:Tf0883edisabledTff7b72) Tb4b4b4{ Tff7b72colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--inkTb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364tabTb4b4b4.T56d364active Tb4b4b4{ Tff7b72colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--inkTb4b4b4)Tb4b4b4; Tff7b72border-bottom-colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--accentTb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364tabTb4b4b4:Tf0883edisabled Tb4b4b4{ Tff7b72opacityTb4b4b4: T79c0ff0.4Tb4b4b4; Tff7b72cursorTb4b4b4: Tff7b72not-allowedTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364body Tb4b4b4{ Tff7b72flexTb4b4b4: T79c0ff1 T79c0ff1 Tff7b72autoTb4b4b4; Tff7b72min-heightTb4b4b4: T79c0ff0Tb4b4b4; Tff7b72displayTb4b4b4: Tff7b72flexTb4b4b4; Tff7b72flex-directionTb4b4b4: Tff7b72columnTb4b4b4; Tff7b72overflowTb4b4b4: Tff7b72hiddenTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364tab-body Tb4b4b4{ Tff7b72flexTb4b4b4: T79c0ff1 T79c0ff1 Tff7b72autoTb4b4b4; Tff7b72min-heightTb4b4b4: T79c0ff0Tb4b4b4; Tff7b72paddingTb4b4b4: T79c0ff16Tffa657pxTb4b4b4; Tff7b72overflowTb4b4b4: Tff7b72autoTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364tab-bodyTb4b4b4.T56d364no-pad Tb4b4b4{ Tff7b72paddingTb4b4b4: T79c0ff0Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364tab-body Tff7b72h2 Tb4b4b4{ Tff7b72marginTb4b4b4: T79c0ff0 T79c0ff0 T79c0ff12Tffa657pxTb4b4b4; Tff7b72font-sizeTb4b4b4: T79c0ff16Tffa657pxTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364tab-body Tff7b72h3 Tb4b4b4{ Tff7b72marginTb4b4b4: T79c0ff16Tffa657px T79c0ff0 T79c0ff8Tffa657pxTb4b4b4; Tff7b72font-sizeTb4b4b4: T79c0ff13Tffa657pxTb4b4b4; Tff7b72colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--mutedTb4b4b4)Tb4b4b4; Tff7b72text-transformTb4b4b4: Tff7b72uppercaseTb4b4b4; Tff7b72letter-spacingTb4b4b4: T79c0ff0.04Tffa657emTb4b4b4; Tb4b4b4}
T8b949e/* Namespace panel headings: h2 for the root, descending tags for nested sub-sections.
depth-1 = section (under root, uppercase + accent bar)
depth-2 = sub-section (smaller, mixed case, fainter bar)
depth-3 = sub-sub-section (further indented, dashed bar) */
Tb4b4b4.T56d364tab-body Tff7b72h2Tb4b4b4.T56d364ns-h Tb4b4b4{ Tff7b72marginTb4b4b4: T79c0ff0 T79c0ff0 T79c0ff8Tffa657pxTb4b4b4; Tff7b72font-sizeTb4b4b4: T79c0ff17Tffa657pxTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364tab-body Tff7b72h3Tb4b4b4.T56d364ns-subTb4b4b4.T56d364depth-1 Tb4b4b4{ Tff7b72marginTb4b4b4: T79c0ff22Tffa657px T79c0ff0 T79c0ff6Tffa657pxTb4b4b4; Tff7b72paddingTb4b4b4: T79c0ff4Tffa657px T79c0ff0 T79c0ff4Tffa657px T79c0ff10Tffa657pxTb4b4b4; Tff7b72border-leftTb4b4b4: T79c0ff3Tffa657px Tff7b72solid Td2a8ffvarTb4b4b4(Te6edf3--accentTb4b4b4)Tb4b4b4; Tff7b72font-sizeTb4b4b4: T79c0ff12Tffa657pxTb4b4b4; Tff7b72colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--inkTb4b4b4)Tb4b4b4; Tff7b72text-transformTb4b4b4: Tff7b72uppercaseTb4b4b4; Tff7b72letter-spacingTb4b4b4: T79c0ff0.05Tffa657emTb4b4b4; Tff7b72font-weightTb4b4b4: T79c0ff600Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364tab-body Tff7b72h4Tb4b4b4.T56d364ns-subTb4b4b4.T56d364depth-2 Tb4b4b4{ Tff7b72marginTb4b4b4: T79c0ff18Tffa657px T79c0ff0 T79c0ff6Tffa657pxTb4b4b4; Tff7b72paddingTb4b4b4: T79c0ff3Tffa657px T79c0ff0 T79c0ff3Tffa657px T79c0ff10Tffa657pxTb4b4b4; Tff7b72border-leftTb4b4b4: T79c0ff2Tffa657px Tff7b72solid Tffa657rgbaTb4b4b4(T79c0ff37Tb4b4b4,T79c0ff99Tb4b4b4,T79c0ff235Tb4b4b4,T79c0ff0.5Tb4b4b4)Tb4b4b4; Tff7b72font-sizeTb4b4b4: T79c0ff12Tffa657pxTb4b4b4; Tff7b72colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--inkTb4b4b4)Tb4b4b4; Tff7b72font-weightTb4b4b4: T79c0ff600Tb4b4b4; Tff7b72text-transformTb4b4b4: Tff7b72noneTb4b4b4; Tff7b72letter-spacingTb4b4b4: T79c0ff0Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364tab-body Tff7b72h5Tb4b4b4.T56d364ns-subTb4b4b4.T56d364depth-3 Tb4b4b4{ Tff7b72marginTb4b4b4: T79c0ff14Tffa657px T79c0ff0 T79c0ff5Tffa657pxTb4b4b4; Tff7b72paddingTb4b4b4: T79c0ff2Tffa657px T79c0ff0 T79c0ff2Tffa657px T79c0ff10Tffa657pxTb4b4b4; Tff7b72border-leftTb4b4b4: T79c0ff1Tffa657px Tff7b72dashed Td2a8ffvarTb4b4b4(Te6edf3--mutedTb4b4b4)Tb4b4b4; Tff7b72font-sizeTb4b4b4: T79c0ff11Tffa657pxTb4b4b4; Tff7b72colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--mutedTb4b4b4)Tb4b4b4; Tff7b72font-weightTb4b4b4: T79c0ff600Tb4b4b4; Tff7b72text-transformTb4b4b4: Tff7b72noneTb4b4b4; Tff7b72letter-spacingTb4b4b4: T79c0ff0Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364ns-sub-fields Tb4b4b4{ Tff7b72padding-leftTb4b4b4: T79c0ff10Tffa657pxTb4b4b4; Tff7b72border-leftTb4b4b4: T79c0ff1Tffa657px Tff7b72dotted Tffa657rgbaTb4b4b4(T79c0ff107Tb4b4b4,T79c0ff114Tb4b4b4,T79c0ff128Tb4b4b4,T79c0ff0.18Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364kv Tb4b4b4{ Tff7b72border-collapseTb4b4b4: Tff7b72collapseTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364kv Tff7b72td Tb4b4b4{ Tff7b72paddingTb4b4b4: T79c0ff4Tffa657px T79c0ff12Tffa657px T79c0ff4Tffa657px T79c0ff0Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364kv Tff7b72tdTb4b4b4:Tf0883efirst-child Tb4b4b4{ Tff7b72colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--mutedTb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364field Tb4b4b4{ Tff7b72displayTb4b4b4: Tff7b72gridTb4b4b4; Tff7b72grid-template-columnsTb4b4b4: T79c0ff220Tffa657px T79c0ff1Te6edf3frTb4b4b4; Tff7b72gapTb4b4b4: T79c0ff12Tffa657pxTb4b4b4; Tff7b72paddingTb4b4b4: T79c0ff8Tffa657px T79c0ff0Tb4b4b4; Tff7b72align-itemsTb4b4b4: Tff7b72centerTb4b4b4; Tff7b72border-bottomTb4b4b4: T79c0ff1Tffa657px Tff7b72solid Td2a8ffvarTb4b4b4(Te6edf3--borderTb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364field Tff7b72label Tb4b4b4{ Tff7b72colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--inkTb4b4b4)Tb4b4b4; Tff7b72font-weightTb4b4b4: T79c0ff500Tb4b4b4; Tff7b72displayTb4b4b4: Tff7b72flexTb4b4b4; Tff7b72align-itemsTb4b4b4: Tff7b72centerTb4b4b4; Tff7b72gapTb4b4b4: T79c0ff6Tffa657pxTb4b4b4; Tff7b72flex-wrapTb4b4b4: Tff7b72wrapTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364field Tff7b72inputTff7b72[Tff7b72typeTff7b72=Tff7b72textTff7b72]Tff7b72, Tb4b4b4.T56d364field Tff7b72inputTff7b72[Tff7b72typeTff7b72=Tff7b72numberTff7b72]Tff7b72, Tb4b4b4.T56d364field Tff7b72inputTff7b72[Tff7b72typeTff7b72=Tff7b72passwordTff7b72]Tff7b72, Tb4b4b4.T56d364field Tff7b72textareaTff7b72, Tb4b4b4.T56d364field Tff7b72select Tb4b4b4{
Tff7b72fontTb4b4b4: Tff7b72inheritTb4b4b4; Tff7b72paddingTb4b4b4: T79c0ff5Tffa657px T79c0ff8Tffa657pxTb4b4b4; Tff7b72borderTb4b4b4: T79c0ff1Tffa657px Tff7b72solid Td2a8ffvarTb4b4b4(Te6edf3--borderTb4b4b4)Tb4b4b4; Tff7b72border-radiusTb4b4b4: T79c0ff4Tffa657pxTb4b4b4; Tff7b72backgroundTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--panelTb4b4b4)Tb4b4b4; Tff7b72colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--inkTb4b4b4)Tb4b4b4; Tff7b72widthTb4b4b4: T79c0ff100Tffa657%Tb4b4b4; Tff7b72max-widthTb4b4b4: T79c0ff360Tffa657pxTb4b4b4;
Tb4b4b4}
Tb4b4b4.T56d364fieldTb4b4b4.T56d364has-err Tff7b72inputTff7b72, Tb4b4b4.T56d364fieldTb4b4b4.T56d364has-err Tff7b72textareaTff7b72, Tb4b4b4.T56d364fieldTb4b4b4.T56d364has-err Tff7b72select Tb4b4b4{ Tff7b72border-colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--errTb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364field Tb4b4b4.T56d364err Tb4b4b4{ Tff7b72grid-columnTb4b4b4: T79c0ff2Tb4b4b4; Tff7b72colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--errTb4b4b4)Tb4b4b4; Tff7b72font-sizeTb4b4b4: T79c0ff12Tffa657pxTb4b4b4; Tff7b72min-heightTb4b4b4: T79c0ff0Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364badge Tb4b4b4{ Tff7b72displayTb4b4b4: Tff7b72inline-blockTb4b4b4; Tff7b72paddingTb4b4b4: T79c0ff1Tffa657px T79c0ff6Tffa657pxTb4b4b4; Tff7b72border-radiusTb4b4b4: T79c0ff3Tffa657pxTb4b4b4; Tff7b72font-sizeTb4b4b4: T79c0ff11Tffa657pxTb4b4b4; Tff7b72font-weightTb4b4b4: T79c0ff500Tb4b4b4; Tff7b72line-heightTb4b4b4: T79c0ff1.4Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364badgeTb4b4b4.T56d364ro Tb4b4b4{ Tff7b72backgroundTb4b4b4: Tffa657rgbaTb4b4b4(T79c0ff107Tb4b4b4,T79c0ff114Tb4b4b4,T79c0ff128Tb4b4b4,T79c0ff0.15Tb4b4b4)Tb4b4b4; Tff7b72colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--mutedTb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364badgeTb4b4b4.T56d364wo Tb4b4b4{ Tff7b72backgroundTb4b4b4: Tffa657rgbaTb4b4b4(T79c0ff180Tb4b4b4,T79c0ff131Tb4b4b4,T79c0ff9Tb4b4b4,T79c0ff0.18Tb4b4b4)Tb4b4b4; Tff7b72colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--warnTb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364badgeTb4b4b4.T56d364secret Tb4b4b4{ Tff7b72backgroundTb4b4b4: Tffa657rgbaTb4b4b4(T79c0ff180Tb4b4b4,T79c0ff131Tb4b4b4,T79c0ff9Tb4b4b4,T79c0ff0.15Tb4b4b4)Tb4b4b4; Tff7b72colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--warnTb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364badgeTb4b4b4.T56d364reboot Tb4b4b4{ Tff7b72backgroundTb4b4b4: Tffa657rgbaTb4b4b4(T79c0ff37Tb4b4b4,T79c0ff99Tb4b4b4,T79c0ff235Tb4b4b4,T79c0ff0.15Tb4b4b4)Tb4b4b4; Tff7b72colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--accentTb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364badgeTb4b4b4.T56d364draft Tb4b4b4{ Tff7b72backgroundTb4b4b4: Tffa657rgbaTb4b4b4(T79c0ff37Tb4b4b4,T79c0ff99Tb4b4b4,T79c0ff235Tb4b4b4,T79c0ff0.15Tb4b4b4)Tb4b4b4; Tff7b72colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--accentTb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364badgeTb4b4b4.T56d364set-only Tb4b4b4{ Tff7b72backgroundTb4b4b4: Tffa657rgbaTb4b4b4(T79c0ff107Tb4b4b4,T79c0ff114Tb4b4b4,T79c0ff128Tb4b4b4,T79c0ff0.18Tb4b4b4)Tb4b4b4; Tff7b72colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--mutedTb4b4b4)Tb4b4b4; Tff7b72borderTb4b4b4: T79c0ff1Tffa657px Tff7b72dashed Td2a8ffvarTb4b4b4(Te6edf3--borderTb4b4b4)Tb4b4b4; Tff7b72paddingTb4b4b4: T79c0ff0 T79c0ff5Tffa657pxTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364set-only-banner Tb4b4b4{ Tff7b72marginTb4b4b4: T79c0ff8Tffa657px T79c0ff0 T79c0ff12Tffa657pxTb4b4b4; Tff7b72paddingTb4b4b4: T79c0ff8Tffa657px T79c0ff12Tffa657pxTb4b4b4; Tff7b72backgroundTb4b4b4: Tffa657rgbaTb4b4b4(T79c0ff107Tb4b4b4,T79c0ff114Tb4b4b4,T79c0ff128Tb4b4b4,T79c0ff0.10Tb4b4b4)Tb4b4b4; Tff7b72border-leftTb4b4b4: T79c0ff3Tffa657px Tff7b72solid Td2a8ffvarTb4b4b4(Te6edf3--mutedTb4b4b4)Tb4b4b4; Tff7b72colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--inkTb4b4b4)Tb4b4b4; Tff7b72font-sizeTb4b4b4: T79c0ff12Tffa657pxTb4b4b4; Tff7b72line-heightTb4b4b4: T79c0ff1.45Tb4b4b4; Tff7b72border-radiusTb4b4b4: T79c0ff3Tffa657pxTb4b4b4; Tb4b4b4}
T8b949e/* Read-only info fields — render the value as static text, not an input. */
Tb4b4b4.T56d364fieldTb4b4b4.T56d364ro-info Tb4b4b4.T56d364ro-value Tb4b4b4{ Tff7b72fontTb4b4b4: T79c0ff12Tffa657pxTff7b72/T79c0ff1.45 Te6edf3ui-monospaceTb4b4b4, Te6edf3SFMono-RegularTb4b4b4, Te6edf3MenloTb4b4b4, Tff7b72monospaceTb4b4b4; Tff7b72colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--inkTb4b4b4)Tb4b4b4; Tff7b72paddingTb4b4b4: T79c0ff5Tffa657px T79c0ff10Tffa657pxTb4b4b4; Tff7b72backgroundTb4b4b4: Tffa657rgbaTb4b4b4(T79c0ff107Tb4b4b4,T79c0ff114Tb4b4b4,T79c0ff128Tb4b4b4,T79c0ff0.08Tb4b4b4)Tb4b4b4; Tff7b72border-radiusTb4b4b4: T79c0ff4Tffa657pxTb4b4b4; Tff7b72max-widthTb4b4b4: T79c0ff360Tffa657pxTb4b4b4; Tff7b72word-breakTb4b4b4: Te6edf3break-allTb4b4b4; Tff7b72white-spaceTb4b4b4: Tff7b72pre-wrapTb4b4b4; Tff7b72min-heightTb4b4b4: T79c0ff16Tffa657pxTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364fieldTb4b4b4.T56d364ro-info Tb4b4b4.T56d364ro-valueTb4b4b4.T56d364empty Tb4b4b4{ Tff7b72colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--mutedTb4b4b4)Tb4b4b4; Tff7b72font-styleTb4b4b4: Tff7b72italicTb4b4b4; Tb4b4b4}
T8b949e/* Write-only command fields — input plus a Send button that fires set+commit. */
Tb4b4b4.T56d364fieldTb4b4b4.T56d364wo-action Tb4b4b4.T56d364wo-controls Tb4b4b4{ Tff7b72displayTb4b4b4: Tff7b72flexTb4b4b4; Tff7b72gapTb4b4b4: T79c0ff8Tffa657pxTb4b4b4; Tff7b72align-itemsTb4b4b4: Tff7b72centerTb4b4b4; Tff7b72flex-wrapTb4b4b4: Tff7b72wrapTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364fieldTb4b4b4.T56d364wo-action Tb4b4b4.T56d364wo-controls Tff7b72inputTff7b72, Tb4b4b4.T56d364fieldTb4b4b4.T56d364wo-action Tb4b4b4.T56d364wo-controls Tff7b72selectTff7b72, Tb4b4b4.T56d364fieldTb4b4b4.T56d364wo-action Tb4b4b4.T56d364wo-controls Tff7b72textarea Tb4b4b4{ Tff7b72flexTb4b4b4: T79c0ff1 T79c0ff1 Tff7b72autoTb4b4b4; Tff7b72min-widthTb4b4b4: T79c0ff180Tffa657pxTb4b4b4; Tff7b72max-widthTb4b4b4: T79c0ff360Tffa657pxTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364fieldTb4b4b4.T56d364wo-action Tb4b4b4.T56d364wo-send Tb4b4b4{ Tff7b72paddingTb4b4b4: T79c0ff5Tffa657px T79c0ff14Tffa657pxTb4b4b4; Tff7b72backgroundTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--accentTb4b4b4)Tb4b4b4; Tff7b72colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--accent-inkTb4b4b4)Tb4b4b4; Tff7b72borderTb4b4b4: T79c0ff1Tffa657px Tff7b72solid Td2a8ffvarTb4b4b4(Te6edf3--accentTb4b4b4)Tb4b4b4; Tff7b72border-radiusTb4b4b4: T79c0ff4Tffa657pxTb4b4b4; Tff7b72cursorTb4b4b4: Tff7b72pointerTb4b4b4; Tff7b72fontTb4b4b4: Tff7b72inheritTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364fieldTb4b4b4.T56d364wo-action Tb4b4b4.T56d364wo-sendTb4b4b4:Tf0883ehoverTb4b4b4:Tf0883enotTff7b72(Tb4b4b4:Tf0883edisabledTff7b72) Tb4b4b4{ Tff7b72opacityTb4b4b4: T79c0ff0.9Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364fieldTb4b4b4.T56d364wo-action Tb4b4b4.T56d364wo-sendTb4b4b4:Tf0883edisabled Tb4b4b4{ Tff7b72opacityTb4b4b4: T79c0ff0.5Tb4b4b4; Tff7b72cursorTb4b4b4: Tff7b72not-allowedTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364ns-toolbar Tb4b4b4{ Tff7b72displayTb4b4b4: Tff7b72flexTb4b4b4; Tff7b72gapTb4b4b4: T79c0ff8Tffa657pxTb4b4b4; Tff7b72padding-bottomTb4b4b4: T79c0ff12Tffa657pxTb4b4b4; Tff7b72margin-bottomTb4b4b4: T79c0ff8Tffa657pxTb4b4b4; Tff7b72border-bottomTb4b4b4: T79c0ff1Tffa657px Tff7b72solid Td2a8ffvarTb4b4b4(Te6edf3--borderTb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364ns-toolbar Tff7b72button Tb4b4b4{ Tff7b72fontTb4b4b4: Tff7b72inheritTb4b4b4; Tff7b72paddingTb4b4b4: T79c0ff5Tffa657px T79c0ff12Tffa657pxTb4b4b4; Tff7b72borderTb4b4b4: T79c0ff1Tffa657px Tff7b72solid Td2a8ffvarTb4b4b4(Te6edf3--borderTb4b4b4)Tb4b4b4; Tff7b72border-radiusTb4b4b4: T79c0ff4Tffa657pxTb4b4b4; Tff7b72backgroundTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--panelTb4b4b4)Tb4b4b4; Tff7b72colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--inkTb4b4b4)Tb4b4b4; Tff7b72cursorTb4b4b4: Tff7b72pointerTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364ns-toolbar Tff7b72buttonTb4b4b4:Tf0883edisabled Tb4b4b4{ Tff7b72opacityTb4b4b4: T79c0ff0.5Tb4b4b4; Tff7b72cursorTb4b4b4: Tff7b72not-allowedTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364bottombar Tb4b4b4{ Tff7b72displayTb4b4b4: Tff7b72flexTb4b4b4; Tff7b72align-itemsTb4b4b4: Tff7b72centerTb4b4b4; Tff7b72gapTb4b4b4: T79c0ff8Tffa657pxTb4b4b4; Tff7b72paddingTb4b4b4: T79c0ff10Tffa657px T79c0ff12Tffa657pxTb4b4b4; Tff7b72backgroundTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--panelTb4b4b4)Tb4b4b4; Tff7b72border-topTb4b4b4: T79c0ff1Tffa657px Tff7b72solid Td2a8ffvarTb4b4b4(Te6edf3--borderTb4b4b4)Tb4b4b4; Tff7b72flexTb4b4b4: T79c0ff0 T79c0ff0 Tff7b72autoTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364bottombar Tff7b72button Tb4b4b4{ Tff7b72fontTb4b4b4: Tff7b72inheritTb4b4b4; Tff7b72paddingTb4b4b4: T79c0ff6Tffa657px T79c0ff14Tffa657pxTb4b4b4; Tff7b72borderTb4b4b4: T79c0ff1Tffa657px Tff7b72solid Td2a8ffvarTb4b4b4(Te6edf3--borderTb4b4b4)Tb4b4b4; Tff7b72border-radiusTb4b4b4: T79c0ff4Tffa657pxTb4b4b4; Tff7b72backgroundTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--panelTb4b4b4)Tb4b4b4; Tff7b72colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--inkTb4b4b4)Tb4b4b4; Tff7b72cursorTb4b4b4: Tff7b72pointerTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364bottombar Tff7b72buttonTb4b4b4:Tf0883edisabled Tb4b4b4{ Tff7b72opacityTb4b4b4: T79c0ff0.5Tb4b4b4; Tff7b72cursorTb4b4b4: Tff7b72not-allowedTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364bottombar Tff7b72buttonTb4b4b4:Tf0883edisabledTb4b4b4.T56d364primary Tb4b4b4{ Tff7b72backgroundTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--panelTb4b4b4)Tb4b4b4; Tff7b72colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--mutedTb4b4b4)Tb4b4b4; Tff7b72border-colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--borderTb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364status-sec Tb4b4b4{ Tff7b72margin-bottomTb4b4b4: T79c0ff18Tffa657pxTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364config-tab Tb4b4b4{ Tff7b72flexTb4b4b4: T79c0ff1 T79c0ff1 Tff7b72autoTb4b4b4; Tff7b72min-heightTb4b4b4: T79c0ff0Tb4b4b4; Tff7b72displayTb4b4b4: Tff7b72flexTb4b4b4; Tff7b72paddingTb4b4b4: T79c0ff0Tb4b4b4; Tff7b72overflowTb4b4b4: Tff7b72hiddenTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364sidenav Tb4b4b4{ Tff7b72widthTb4b4b4: T79c0ff180Tffa657pxTb4b4b4; Tff7b72flexTb4b4b4: T79c0ff0 T79c0ff0 Tff7b72autoTb4b4b4; Tff7b72border-rightTb4b4b4: T79c0ff1Tffa657px Tff7b72solid Td2a8ffvarTb4b4b4(Te6edf3--borderTb4b4b4)Tb4b4b4; Tff7b72overflow-yTb4b4b4: Tff7b72autoTb4b4b4; Tff7b72paddingTb4b4b4: T79c0ff8Tffa657px T79c0ff0Tb4b4b4; Tff7b72backgroundTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--panelTb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364sidenav-btn Tb4b4b4{ Tff7b72displayTb4b4b4: Tff7b72blockTb4b4b4; Tff7b72widthTb4b4b4: T79c0ff100Tffa657%Tb4b4b4; Tff7b72text-alignTb4b4b4: Tff7b72leftTb4b4b4; Tff7b72paddingTb4b4b4: T79c0ff8Tffa657px T79c0ff16Tffa657pxTb4b4b4; Tff7b72backgroundTb4b4b4: Tff7b72transparentTb4b4b4; Tff7b72borderTb4b4b4: Tff7b72noneTb4b4b4; Tff7b72colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--inkTb4b4b4)Tb4b4b4; Tff7b72cursorTb4b4b4: Tff7b72pointerTb4b4b4; Tff7b72fontTb4b4b4: Tff7b72inheritTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364sidenav-btnTb4b4b4:Tf0883ehover Tb4b4b4{ Tff7b72backgroundTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--hoverTb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364sidenav-btnTb4b4b4.T56d364active Tb4b4b4{ Tff7b72backgroundTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--accentTb4b4b4)Tb4b4b4; Tff7b72colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--accent-inkTb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364sidenav-btn Tb4b4b4.T56d364dot Tb4b4b4{ Tff7b72displayTb4b4b4: Tff7b72inline-blockTb4b4b4; Tff7b72widthTb4b4b4: T79c0ff6Tffa657pxTb4b4b4; Tff7b72heightTb4b4b4: T79c0ff6Tffa657pxTb4b4b4; Tff7b72border-radiusTb4b4b4: T79c0ff50Tffa657%Tb4b4b4; Tff7b72backgroundTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--accentTb4b4b4)Tb4b4b4; Tff7b72margin-leftTb4b4b4: T79c0ff6Tffa657pxTb4b4b4; Tff7b72vertical-alignTb4b4b4: Tff7b72middleTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364sidenav-btnTb4b4b4.T56d364active Tb4b4b4.T56d364dot Tb4b4b4{ Tff7b72backgroundTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--accent-inkTb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364sidenav-detail Tb4b4b4{ Tff7b72flexTb4b4b4: T79c0ff1 T79c0ff1 Tff7b72autoTb4b4b4; Tff7b72min-widthTb4b4b4: T79c0ff0Tb4b4b4; Tff7b72min-heightTb4b4b4: T79c0ff0Tb4b4b4; Tff7b72paddingTb4b4b4: T79c0ff16Tffa657pxTb4b4b4; Tff7b72overflow-yTb4b4b4: Tff7b72autoTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364logs-tab Tb4b4b4{ Tff7b72flexTb4b4b4: T79c0ff1 T79c0ff1 Tff7b72autoTb4b4b4; Tff7b72min-heightTb4b4b4: T79c0ff0Tb4b4b4; Tff7b72displayTb4b4b4: Tff7b72flexTb4b4b4; Tff7b72flex-directionTb4b4b4: Tff7b72columnTb4b4b4; Tff7b72positionTb4b4b4: Tff7b72relativeTb4b4b4; Tff7b72paddingTb4b4b4: T79c0ff0Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364logs-toolbar Tb4b4b4{ Tff7b72displayTb4b4b4: Tff7b72flexTb4b4b4; Tff7b72align-itemsTb4b4b4: Tff7b72centerTb4b4b4; Tff7b72gapTb4b4b4: T79c0ff8Tffa657pxTb4b4b4; Tff7b72paddingTb4b4b4: T79c0ff6Tffa657px T79c0ff12Tffa657pxTb4b4b4; Tff7b72backgroundTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--panelTb4b4b4)Tb4b4b4; Tff7b72border-bottomTb4b4b4: T79c0ff1Tffa657px Tff7b72solid Td2a8ffvarTb4b4b4(Te6edf3--borderTb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364logs-toolbar Tff7b72button Tb4b4b4{ Tff7b72fontTb4b4b4: Tff7b72inheritTb4b4b4; Tff7b72paddingTb4b4b4: T79c0ff4Tffa657px T79c0ff10Tffa657pxTb4b4b4; Tff7b72borderTb4b4b4: T79c0ff1Tffa657px Tff7b72solid Td2a8ffvarTb4b4b4(Te6edf3--borderTb4b4b4)Tb4b4b4; Tff7b72border-radiusTb4b4b4: T79c0ff4Tffa657pxTb4b4b4; Tff7b72backgroundTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--panelTb4b4b4)Tb4b4b4; Tff7b72colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--inkTb4b4b4)Tb4b4b4; Tff7b72cursorTb4b4b4: Tff7b72pointerTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364logs-toolbar Tff7b72buttonTb4b4b4:Tf0883ehover Tb4b4b4{ Tff7b72backgroundTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--hoverTb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364logs Tb4b4b4{ Tff7b72flexTb4b4b4: T79c0ff1 T79c0ff1 Tff7b72autoTb4b4b4; Tff7b72min-heightTb4b4b4: T79c0ff0Tb4b4b4; Tff7b72overflowTb4b4b4: Tff7b72autoTb4b4b4; Tff7b72paddingTb4b4b4: T79c0ff8Tffa657px T79c0ff12Tffa657pxTb4b4b4; Tff7b72fontTb4b4b4: T79c0ff12Tffa657pxTff7b72/T79c0ff1.5 Te6edf3ui-monospaceTb4b4b4, Te6edf3SFMono-RegularTb4b4b4, Te6edf3MenloTb4b4b4, Tff7b72monospaceTb4b4b4; Tff7b72backgroundTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--panelTb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364log-line Tb4b4b4{ Tff7b72white-spaceTb4b4b4: Tff7b72pre-wrapTb4b4b4; Tff7b72word-breakTb4b4b4: Te6edf3break-allTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364follow-pill Tb4b4b4{ Tff7b72positionTb4b4b4: Tff7b72absoluteTb4b4b4; Tff7b72bottomTb4b4b4: T79c0ff14Tffa657pxTb4b4b4; Tff7b72rightTb4b4b4: T79c0ff18Tffa657pxTb4b4b4; Tff7b72paddingTb4b4b4: T79c0ff5Tffa657px T79c0ff12Tffa657pxTb4b4b4; Tff7b72border-radiusTb4b4b4: T79c0ff999Tffa657pxTb4b4b4; Tff7b72borderTb4b4b4: T79c0ff1Tffa657px Tff7b72solid Td2a8ffvarTb4b4b4(Te6edf3--borderTb4b4b4)Tb4b4b4; Tff7b72backgroundTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--accentTb4b4b4)Tb4b4b4; Tff7b72colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--accent-inkTb4b4b4)Tb4b4b4; Tff7b72cursorTb4b4b4: Tff7b72pointerTb4b4b4; Tff7b72fontTb4b4b4: Tff7b72inheritTb4b4b4; Tff7b72box-shadowTb4b4b4: T79c0ff0 T79c0ff1Tffa657px T79c0ff4Tffa657px Tffa657rgbaTb4b4b4(T79c0ff0Tb4b4b4,T79c0ff0Tb4b4b4,T79c0ff0Tb4b4b4,T79c0ff0.2Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364notice Tb4b4b4{ Tff7b72paddingTb4b4b4: T79c0ff8Tffa657px T79c0ff12Tffa657pxTb4b4b4; Tff7b72backgroundTb4b4b4: Tffa657rgbaTb4b4b4(T79c0ff180Tb4b4b4,T79c0ff131Tb4b4b4,T79c0ff9Tb4b4b4,T79c0ff0.12Tb4b4b4)Tb4b4b4; Tff7b72colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--warnTb4b4b4)Tb4b4b4; Tff7b72border-radiusTb4b4b4: T79c0ff4Tffa657pxTb4b4b4; Tff7b72margin-bottomTb4b4b4: T79c0ff12Tffa657pxTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364toasts Tb4b4b4{ Tff7b72positionTb4b4b4: Tff7b72fixedTb4b4b4; Tff7b72topTb4b4b4: T79c0ff56Tffa657pxTb4b4b4; Tff7b72rightTb4b4b4: T79c0ff16Tffa657pxTb4b4b4; Tff7b72displayTb4b4b4: Tff7b72flexTb4b4b4; Tff7b72flex-directionTb4b4b4: Tff7b72columnTb4b4b4; Tff7b72gapTb4b4b4: T79c0ff8Tffa657pxTb4b4b4; Tff7b72z-indexTb4b4b4: T79c0ff1000Tb4b4b4; Tff7b72pointer-eventsTb4b4b4: Tff7b72noneTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364toast Tb4b4b4{ Tff7b72paddingTb4b4b4: T79c0ff10Tffa657px T79c0ff14Tffa657pxTb4b4b4; Tff7b72backgroundTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--panelTb4b4b4)Tb4b4b4; Tff7b72borderTb4b4b4: T79c0ff1Tffa657px Tff7b72solid Td2a8ffvarTb4b4b4(Te6edf3--borderTb4b4b4)Tb4b4b4; Tff7b72border-left-widthTb4b4b4: T79c0ff3Tffa657pxTb4b4b4; Tff7b72border-radiusTb4b4b4: T79c0ff4Tffa657pxTb4b4b4; Tff7b72box-shadowTb4b4b4: T79c0ff0 T79c0ff2Tffa657px T79c0ff12Tffa657px Tffa657rgbaTb4b4b4(T79c0ff0Tb4b4b4,T79c0ff0Tb4b4b4,T79c0ff0Tb4b4b4,T79c0ff0.18Tb4b4b4)Tb4b4b4; Tff7b72min-widthTb4b4b4: T79c0ff220Tffa657pxTb4b4b4; Tff7b72max-widthTb4b4b4: T79c0ff360Tffa657pxTb4b4b4; Tff7b72opacityTb4b4b4: T79c0ff0Tb4b4b4; Tff7b72transformTb4b4b4: Tffa657translateYTb4b4b4(T79c0ff-8Tffa657pxTb4b4b4)Tb4b4b4; Tff7b72transitionTb4b4b4: Tff7b72opacity T79c0ff0.2Tffa657sTb4b4b4, Tff7b72transform T79c0ff0.2Tffa657sTb4b4b4; Tff7b72pointer-eventsTb4b4b4: Tff7b72autoTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364toastTb4b4b4.T56d364show Tb4b4b4{ Tff7b72opacityTb4b4b4: T79c0ff1Tb4b4b4; Tff7b72transformTb4b4b4: Tffa657translateYTb4b4b4(T79c0ff0Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364toastTb4b4b4.T56d364ok Tb4b4b4{ Tff7b72border-left-colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--okTb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364toastTb4b4b4.T56d364err Tb4b4b4{ Tff7b72border-left-colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--errTb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364toastTb4b4b4.T56d364warn Tb4b4b4{ Tff7b72border-left-colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--warnTb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364toastTb4b4b4.T56d364info Tb4b4b4{ Tff7b72border-left-colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--accentTb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72pre Tb4b4b4{ Tff7b72fontTb4b4b4: T79c0ff12Tffa657pxTff7b72/T79c0ff1.5 Te6edf3ui-monospaceTb4b4b4, Te6edf3MenloTb4b4b4, Tff7b72monospaceTb4b4b4; Tb4b4b4}
T8b949e/* Node Config */
Tb4b4b4.T56d364kv-info Tb4b4b4{ Tff7b72border-collapseTb4b4b4: Tff7b72collapseTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364kv-info Tff7b72td Tb4b4b4{ Tff7b72paddingTb4b4b4: T79c0ff4Tffa657px T79c0ff12Tffa657px T79c0ff4Tffa657px T79c0ff0Tb4b4b4; Tff7b72vertical-alignTb4b4b4: Tff7b72topTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364kv-info Tff7b72tdTb4b4b4:Tf0883efirst-child Tb4b4b4{ Tff7b72colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--mutedTb4b4b4)Tb4b4b4; Tff7b72white-spaceTb4b4b4: Tff7b72nowrapTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364kv-info Tff7b72tdTb4b4b4.T56d364hash Tb4b4b4{ Tff7b72fontTb4b4b4: T79c0ff11Tffa657pxTff7b72/T79c0ff1.4 Te6edf3ui-monospaceTb4b4b4, Te6edf3MenloTb4b4b4, Tff7b72monospaceTb4b4b4; Tff7b72word-breakTb4b4b4: Te6edf3break-allTb4b4b4; Tff7b72max-widthTb4b4b4: T79c0ff360Tffa657pxTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364ncfg-section Tff7b72h2 Tb4b4b4{ Tff7b72marginTb4b4b4: T79c0ff0 T79c0ff0 T79c0ff8Tffa657pxTb4b4b4; Tff7b72font-sizeTb4b4b4: T79c0ff16Tffa657pxTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364ncfg-trailer Tb4b4b4{ Tff7b72colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--mutedTb4b4b4)Tb4b4b4; Tff7b72font-sizeTb4b4b4: T79c0ff12Tffa657pxTb4b4b4; Tff7b72marginTb4b4b4: T79c0ff8Tffa657px T79c0ff0 T79c0ff12Tffa657pxTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364danger-zone Tb4b4b4{ Tff7b72paddingTb4b4b4: T79c0ff12Tffa657pxTb4b4b4; Tff7b72borderTb4b4b4: T79c0ff1Tffa657px Tff7b72solid Td2a8ffvarTb4b4b4(Te6edf3--errTb4b4b4)Tb4b4b4; Tff7b72border-radiusTb4b4b4: T79c0ff4Tffa657pxTb4b4b4; Tff7b72margin-topTb4b4b4: T79c0ff16Tffa657pxTb4b4b4; Tff7b72backgroundTb4b4b4: Tffa657rgbaTb4b4b4(T79c0ff185Tb4b4b4,T79c0ff28Tb4b4b4,T79c0ff28Tb4b4b4,T79c0ff0.04Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364danger-zone Tff7b72h3 Tb4b4b4{ Tff7b72marginTb4b4b4: T79c0ff0 T79c0ff0 T79c0ff8Tffa657pxTb4b4b4; Tff7b72colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--errTb4b4b4)Tb4b4b4; Tff7b72font-sizeTb4b4b4: T79c0ff13Tffa657pxTb4b4b4; Tff7b72text-transformTb4b4b4: Tff7b72uppercaseTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364danger-zone Tff7b72button Tb4b4b4{ Tff7b72backgroundTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--panelTb4b4b4)Tb4b4b4; Tff7b72borderTb4b4b4: T79c0ff1Tffa657px Tff7b72solid Td2a8ffvarTb4b4b4(Te6edf3--errTb4b4b4)Tb4b4b4; Tff7b72colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--errTb4b4b4)Tb4b4b4; Tff7b72paddingTb4b4b4: T79c0ff6Tffa657px T79c0ff14Tffa657pxTb4b4b4; Tff7b72border-radiusTb4b4b4: T79c0ff4Tffa657pxTb4b4b4; Tff7b72fontTb4b4b4: Tff7b72inheritTb4b4b4; Tff7b72cursorTb4b4b4: Tff7b72pointerTb4b4b4; Tff7b72margin-rightTb4b4b4: T79c0ff6Tffa657pxTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364danger-zone Tff7b72buttonTb4b4b4:Tf0883ehover Tb4b4b4{ Tff7b72backgroundTb4b4b4: Tffa657rgbaTb4b4b4(T79c0ff185Tb4b4b4,T79c0ff28Tb4b4b4,T79c0ff28Tb4b4b4,T79c0ff0.08Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364danger-zone Tff7b72buttonTb4b4b4:Tf0883edisabled Tb4b4b4{ Tff7b72opacityTb4b4b4: T79c0ff0.5Tb4b4b4; Tff7b72cursorTb4b4b4: Tff7b72not-allowedTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364hexview Tb4b4b4{ Tff7b72fontTb4b4b4: T79c0ff11Tffa657pxTff7b72/T79c0ff1.5 Te6edf3ui-monospaceTb4b4b4, Te6edf3MenloTb4b4b4, Tff7b72monospaceTb4b4b4; Tff7b72backgroundTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--panelTb4b4b4)Tb4b4b4; Tff7b72borderTb4b4b4: T79c0ff1Tffa657px Tff7b72solid Td2a8ffvarTb4b4b4(Te6edf3--borderTb4b4b4)Tb4b4b4; Tff7b72border-radiusTb4b4b4: T79c0ff4Tffa657pxTb4b4b4; Tff7b72paddingTb4b4b4: T79c0ff10Tffa657px T79c0ff14Tffa657pxTb4b4b4; Tff7b72overflowTb4b4b4: Tff7b72autoTb4b4b4; Tff7b72max-heightTb4b4b4: T79c0ff480Tffa657pxTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364hexview Tb4b4b4.T56d364hx-row Tb4b4b4{ Tff7b72displayTb4b4b4: Tff7b72flexTb4b4b4; Tff7b72gapTb4b4b4: T79c0ff12Tffa657pxTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364hexview Tb4b4b4.T56d364hx-off Tb4b4b4{ Tff7b72colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--mutedTb4b4b4)Tb4b4b4; Tff7b72flexTb4b4b4: T79c0ff0 T79c0ff0 Tff7b72autoTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364hexview Tb4b4b4.T56d364hx-bytes Tb4b4b4{ Tff7b72flexTb4b4b4: T79c0ff1 T79c0ff1 Tff7b72autoTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364hexview Tb4b4b4.T56d364hx-ascii Tb4b4b4{ Tff7b72colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--mutedTb4b4b4)Tb4b4b4; Tff7b72flexTb4b4b4: T79c0ff0 T79c0ff0 Tff7b72autoTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364hexview Tb4b4b4.T56d364hx-mark Tb4b4b4{ Tff7b72backgroundTb4b4b4: Tffa657rgbaTb4b4b4(T79c0ff37Tb4b4b4,T79c0ff99Tb4b4b4,T79c0ff235Tb4b4b4,T79c0ff0.15Tb4b4b4)Tb4b4b4; Tff7b72border-radiusTb4b4b4: T79c0ff2Tffa657pxTb4b4b4; Tff7b72paddingTb4b4b4: T79c0ff0 T79c0ff2Tffa657pxTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364hexview Tb4b4b4.T56d364hx-legend Tb4b4b4{ Tff7b72colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--mutedTb4b4b4)Tb4b4b4; Tff7b72margin-topTb4b4b4: T79c0ff8Tffa657pxTb4b4b4; Tff7b72font-sizeTb4b4b4: T79c0ff11Tffa657pxTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364hexview Tb4b4b4.T56d364hx-legend Tb4b4b4.T56d364hx-mark Tb4b4b4{ Tff7b72margin-rightTb4b4b4: T79c0ff4Tffa657pxTb4b4b4; Tff7b72paddingTb4b4b4: T79c0ff0 T79c0ff6Tffa657pxTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364eeprom-toolbar Tb4b4b4{ Tff7b72displayTb4b4b4: Tff7b72flexTb4b4b4; Tff7b72gapTb4b4b4: T79c0ff8Tffa657pxTb4b4b4; Tff7b72margin-bottomTb4b4b4: T79c0ff12Tffa657pxTb4b4b4; Tff7b72align-itemsTb4b4b4: Tff7b72centerTb4b4b4; Tff7b72flex-wrapTb4b4b4: Tff7b72wrapTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364eeprom-toolbar Tff7b72button Tb4b4b4{ Tff7b72fontTb4b4b4: Tff7b72inheritTb4b4b4; Tff7b72paddingTb4b4b4: T79c0ff5Tffa657px T79c0ff12Tffa657pxTb4b4b4; Tff7b72borderTb4b4b4: T79c0ff1Tffa657px Tff7b72solid Td2a8ffvarTb4b4b4(Te6edf3--borderTb4b4b4)Tb4b4b4; Tff7b72border-radiusTb4b4b4: T79c0ff4Tffa657pxTb4b4b4; Tff7b72backgroundTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--panelTb4b4b4)Tb4b4b4; Tff7b72colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--inkTb4b4b4)Tb4b4b4; Tff7b72cursorTb4b4b4: Tff7b72pointerTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364eeprom-toolbar Tff7b72buttonTb4b4b4:Tf0883ehover Tb4b4b4{ Tff7b72backgroundTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--hoverTb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364eeprom-toolbar Tff7b72buttonTb4b4b4:Tf0883edisabled Tb4b4b4{ Tff7b72opacityTb4b4b4: T79c0ff0.5Tb4b4b4; Tff7b72cursorTb4b4b4: Tff7b72not-allowedTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364bt-mode-row Tb4b4b4{ Tff7b72displayTb4b4b4: Tff7b72flexTb4b4b4; Tff7b72gapTb4b4b4: T79c0ff8Tffa657pxTb4b4b4; Tff7b72align-itemsTb4b4b4: Tff7b72centerTb4b4b4; Tff7b72marginTb4b4b4: T79c0ff12Tffa657px T79c0ff0Tb4b4b4; Tff7b72flex-wrapTb4b4b4: Tff7b72wrapTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364bt-mode-row Tff7b72button Tb4b4b4{ Tff7b72fontTb4b4b4: Tff7b72inheritTb4b4b4; Tff7b72paddingTb4b4b4: T79c0ff6Tffa657px T79c0ff14Tffa657pxTb4b4b4; Tff7b72borderTb4b4b4: T79c0ff1Tffa657px Tff7b72solid Td2a8ffvarTb4b4b4(Te6edf3--borderTb4b4b4)Tb4b4b4; Tff7b72border-radiusTb4b4b4: T79c0ff4Tffa657pxTb4b4b4; Tff7b72backgroundTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--panelTb4b4b4)Tb4b4b4; Tff7b72colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--inkTb4b4b4)Tb4b4b4; Tff7b72cursorTb4b4b4: Tff7b72pointerTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364bt-mode-row Tff7b72buttonTb4b4b4:Tf0883ehoverTb4b4b4:Tf0883enotTff7b72(Tb4b4b4:Tf0883edisabledTff7b72) Tb4b4b4{ Tff7b72backgroundTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--hoverTb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364bt-mode-row Tff7b72buttonTb4b4b4.T56d364active Tb4b4b4{ Tff7b72backgroundTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--accentTb4b4b4)Tb4b4b4; Tff7b72colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--accent-inkTb4b4b4)Tb4b4b4; Tff7b72border-colorTb4b4b4: Td2a8ffvarTb4b4b4(Te6edf3--accentTb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364bt-mode-row Tff7b72buttonTb4b4b4:Tf0883edisabled Tb4b4b4{ Tff7b72opacityTb4b4b4: T79c0ff0.5Tb4b4b4; Tff7b72cursorTb4b4b4: Tff7b72not-allowedTb4b4b4; Tb4b4b4}
Tb4b4b4.T56d364mode-current Tb4b4b4{ Tff7b72paddingTb4b4b4: T79c0ff10Tffa657px T79c0ff14Tffa657pxTb4b4b4; Tff7b72backgroundTb4b4b4: Tffa657rgbaTb4b4b4(T79c0ff37Tb4b4b4,T79c0ff99Tb4b4b4,T79c0ff235Tb4b4b4,T79c0ff0.08Tb4b4b4)Tb4b4b4; Tff7b72borderTb4b4b4: T79c0ff1Tffa657px Tff7b72solid Td2a8ffvarTb4b4b4(Te6edf3--accentTb4b4b4)Tb4b4b4; Tff7b72border-radiusTb4b4b4: T79c0ff4Tffa657pxTb4b4b4; Tff7b72margin-bottomTb4b4b4: T79c0ff16Tffa657pxTb4b4b4; Tb4b4b4}
T8b949e/* While auto-reconnecting after Reboot now / transport drop: visually disable
panel-body controls. nsState / nodeCfgState are preserved across the window
(see startReconnect) so values stay visible, but edits would be lost when
the post-reconnect fetch overwrites them. */
Tff7b72bodyTb4b4b4.T56d364is-reconnecting Tff7b72inputTff7b72,
Tff7b72bodyTb4b4b4.T56d364is-reconnecting Tff7b72selectTff7b72,
Tff7b72bodyTb4b4b4.T56d364is-reconnecting Tff7b72textareaTff7b72,
Tff7b72bodyTb4b4b4.T56d364is-reconnecting Tff7b72buttonTb4b4b4.T56d364wo-sendTff7b72,
Tff7b72bodyTb4b4b4.T56d364is-reconnecting Tb4b4b4.T56d364ns-toolbar Tff7b72buttonTff7b72,
Tff7b72bodyTb4b4b4.T56d364is-reconnecting Tb4b4b4.T56d364sidenav-detail Tff7b72button Tb4b4b4{
Tff7b72pointer-eventsTb4b4b4: Tff7b72noneTb4b4b4;
Tff7b72opacityTb4b4b4: T79c0ff0.55Tb4b4b4;
Tb4b4b4}
Tb4b4b4<Tb4b4b4/Tff7b72styleTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72headTb4b4b4>
Tb4b4b4<Tff7b72bodyTb4b4b4>
Tb4b4b4<Tff7b72div Te6edf3idTff7b72=Ta5d6ff"app"Tb4b4b4>Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tff7b72div Te6edf3idTff7b72=Ta5d6ff"toasts" Te6edf3classTff7b72=Ta5d6ff"toasts"Tb4b4b4>Tb4b4b4<Tb4b4b4/Tff7b72divTb4b4b4>
Tb4b4b4<Tff7b72scriptTb4b4b4>
Tb4b4b4(Tff7b72functionTb4b4b4(Tb4b4b4)Tb4b4b4{
Ta5d6ff'use strict'Tb4b4b4;

T8b949e// ===== Protocol constants =====
Tff7b72const Te6edf3FENDTff7b72=T79c0ff0xC0Tb4b4b4, Te6edf3FESCTff7b72=T79c0ff0xDBTb4b4b4, Te6edf3TFENDTff7b72=T79c0ff0xDCTb4b4b4, Te6edf3TFESCTff7b72=T79c0ff0xDDTb4b4b4;
Tff7b72const Te6edf3CMD_LOGTff7b72=T79c0ff0x80Tb4b4b4, Te6edf3CMD_PROVISION_REQTff7b72=T79c0ff0x86Tb4b4b4, Te6edf3CMD_PROVISION_RSPTff7b72=T79c0ff0x87Tb4b4b4;
Tff7b72const Te6edf3CMD_RESETTff7b72=T79c0ff0x55Tb4b4b4, Te6edf3CMD_RESET_BYTETff7b72=T79c0ff0xF8Tb4b4b4;
Tff7b72const Te6edf3STAT_CMD_RANGE Tff7b72= Tb4b4b4[T79c0ff0x21Tb4b4b4, T79c0ff0x29Tb4b4b4]Tb4b4b4;

T8b949e// Optional schema baked in at packaging time. When BUNDLED_SCHEMA is non-null
T8b949e// and its hash/version match the device's GetInfo response, the web console
T8b949e// uses it directly and skips the GetSchema round-trip entirely — important
T8b949e// on LoRa where a full schema fetch is ~3 KB of airtime. The placeholder is
T8b949e// replaced by webconsole/package.sh from a build-time schema dump. Shape:
T8b949e// { version: <int>, hash: <uint32>, schemaJson: "<serialised schema>" }
Tff7b72const Te6edf3BUNDLED_SCHEMA Tff7b72= Tff7b72nullTb4b4b4;

Tff7b72const Te6edf3OP Tff7b72= Tb4b4b4{ Te6edf3GetSchemaTff7b72:T79c0ff1Tb4b4b4, Te6edf3GetInfoTff7b72:T79c0ff2Tb4b4b4, Te6edf3GetCapabilitiesTff7b72:T79c0ff3Tb4b4b4, Te6edf3GetStateTff7b72:T79c0ff4Tb4b4b4, Te6edf3SetStateTff7b72:T79c0ff5Tb4b4b4, Te6edf3CommitTff7b72:T79c0ff6Tb4b4b4, Te6edf3DiscardTff7b72:T79c0ff7Tb4b4b4, Te6edf3FactoryResetTff7b72:T79c0ff8Tb4b4b4, Te6edf3RebootTff7b72:T79c0ff9Tb4b4b4, Te6edf3AckTff7b72:T79c0ff100Tb4b4b4, Tf85149ErrorTff7b72:T79c0ff101 Tb4b4b4}Tb4b4b4;
Tff7b72const Te6edf3FT Tff7b72= Tb4b4b4{ Te6edf3NoneTff7b72:T79c0ff0Tb4b4b4, Te6edf3BoolTff7b72:T79c0ff1Tb4b4b4, Te6edf3IntTff7b72:T79c0ff2Tb4b4b4, Te6edf3FloatTff7b72:T79c0ff3Tb4b4b4, Tffa657StringTff7b72:T79c0ff4Tb4b4b4, Te6edf3BytesTff7b72:T79c0ff5Tb4b4b4, Te6edf3EnumTff7b72:T79c0ff6Tb4b4b4, Te6edf3BytesListTff7b72:T79c0ff7Tb4b4b4, Te6edf3VoidTff7b72:T79c0ff8 Tb4b4b4}Tb4b4b4;
T8b949e// Provisioning field flags (Field.h FF_*). Mutually exclusive uses:
T8b949e// - READ_ONLY: info-only field (e.g. metrics). Server has a getter; client
T8b949e// must not draft it. Renders as static value display.
T8b949e// - WRITE_ONLY: command field. Setter fires on Commit; value isn't persisted
T8b949e// or echoed in GET_STATE. Renders as input + Send button that
T8b949e// fires SetState+Commit in a single action. Never enters
T8b949e// the namespace draft store.
Tff7b72const Te6edf3FF Tff7b72= Tb4b4b4{ Te6edf3LIVE_APPLYTff7b72:T79c0ff1Tb4b4b4, Te6edf3REBOOT_REQUIREDTff7b72:T79c0ff2Tb4b4b4, Te6edf3READ_ONLYTff7b72:T79c0ff4Tb4b4b4, Te6edf3SECRETTff7b72:T79c0ff8Tb4b4b4, Te6edf3WRITE_ONLYTff7b72:T79c0ff16 Tb4b4b4}Tb4b4b4;
Tff7b72const Te6edf3ERR_NAMES Tff7b72= Tb4b4b4{ T79c0ff0Tff7b72:Ta5d6ff'Ok'Tb4b4b4, T79c0ff1Tff7b72:Ta5d6ff'BadRequest'Tb4b4b4, T79c0ff2Tff7b72:Ta5d6ff'UnknownOp'Tb4b4b4, T79c0ff3Tff7b72:Ta5d6ff'UnknownNs'Tb4b4b4, T79c0ff4Tff7b72:Ta5d6ff'UnknownField'Tb4b4b4, T79c0ff5Tff7b72:Ta5d6ff'InvalidValue'Tb4b4b4, T79c0ff6Tff7b72:Ta5d6ff'Constraint'Tb4b4b4, T79c0ff7Tff7b72:Ta5d6ff'ReadOnly'Tb4b4b4, T79c0ff8Tff7b72:Ta5d6ff'StorageError'Tb4b4b4, T79c0ff9Tff7b72:Ta5d6ff'NotInitialized'Tb4b4b4, T79c0ff99Tff7b72:Ta5d6ff'Internal' Tb4b4b4}Tb4b4b4;
Tff7b72const Te6edf3FK Tff7b72= Tb4b4b4{ Te6edf3IdTff7b72:T79c0ff1Tb4b4b4, Te6edf3NameTff7b72:T79c0ff2Tb4b4b4, Te6edf3TypeTff7b72:T79c0ff3Tb4b4b4, Te6edf3FlagsTff7b72:T79c0ff4Tb4b4b4, Te6edf3MinITff7b72:T79c0ff5Tb4b4b4, Te6edf3MaxITff7b72:T79c0ff6Tb4b4b4, Te6edf3MinFTff7b72:T79c0ff7Tb4b4b4, Te6edf3MaxFTff7b72:T79c0ff8Tb4b4b4, Te6edf3MaxLenTff7b72:T79c0ff9Tb4b4b4, Te6edf3EnumValuesTff7b72:T79c0ff10Tb4b4b4, Te6edf3EnumLabelsTff7b72:T79c0ff11Tb4b4b4, Te6edf3DefaultTff7b72:T79c0ff12Tb4b4b4, Te6edf3ElementSizeTff7b72:T79c0ff13Tb4b4b4, Te6edf3MaxCountTff7b72:T79c0ff14 Tb4b4b4}Tb4b4b4;
Tff7b72const Te6edf3IK Tff7b72= Tb4b4b4{ Te6edf3FirmwareVersionTff7b72:T79c0ff1Tb4b4b4, Te6edf3SchemaVersionTff7b72:T79c0ff2Tb4b4b4, Te6edf3NeedsRebootTff7b72:T79c0ff3Tb4b4b4, Te6edf3SchemaHashTff7b72:T79c0ff4 Tb4b4b4}Tb4b4b4;
T8b949e// Wire-level transport keys (request-payload and response-sentinel). Reserved
T8b949e// at 100+ to avoid collision with low-numbered field/ns identifiers.
Tff7b72const Te6edf3WK Tff7b72= Tb4b4b4{ Te6edf3ReqCompressTff7b72:T79c0ff100Tb4b4b4, Te6edf3CompressedPayloadTff7b72:T79c0ff101 Tb4b4b4}Tb4b4b4;
T8b949e// heatshrink decoder config — MUST match the firmware build flags in microReticulum heatshrink_config.h.
Tff7b72const Te6edf3HS_WINDOW_BITS Tff7b72= T79c0ff9Tb4b4b4;
Tff7b72const Te6edf3HS_LOOKAHEAD_BITS Tff7b72= T79c0ff4Tb4b4b4;
T8b949e// Ops where a ReqCompress flag is safe to inject in the request payload.
T8b949e// SetState / Commit / Discard use different payload shapes (map keyed by
T8b949e// ns-id, or array) where injecting a flag would conflict; their responses
T8b949e// are also small and don't benefit from compression.
Tff7b72const Te6edf3COMPRESSIBLE_OPS Tff7b72= Tff7b72new Tffa657SetTb4b4b4(Tb4b4b4[
Te6edf3OPTb4b4b4.Te6edf3GetSchemaTb4b4b4, Te6edf3OPTb4b4b4.Te6edf3GetInfoTb4b4b4, Te6edf3OPTb4b4b4.Te6edf3GetCapabilitiesTb4b4b4, Te6edf3OPTb4b4b4.Te6edf3GetStateTb4b4b4,
Te6edf3OPTb4b4b4.Te6edf3FactoryResetTb4b4b4, Te6edf3OPTb4b4b4.Te6edf3RebootTb4b4b4,
Tb4b4b4]Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3GK Tff7b72= Tb4b4b4{ Te6edf3NamespaceFilterTff7b72:T79c0ff1Tb4b4b4, Te6edf3PendingTff7b72:T79c0ff2 Tb4b4b4}Tb4b4b4;
Tff7b72const Te6edf3SK Tff7b72= Tb4b4b4{ Te6edf3AppliedTff7b72:T79c0ff1Tb4b4b4, Te6edf3DraftHasRebootTff7b72:T79c0ff2Tb4b4b4, Te6edf3FieldErrorsTff7b72:T79c0ff3 Tb4b4b4}Tb4b4b4;
Tff7b72const Te6edf3CK Tff7b72= Tb4b4b4{ Te6edf3AppliedTff7b72:T79c0ff1Tb4b4b4, Te6edf3NeedsRebootTff7b72:T79c0ff2 Tb4b4b4}Tb4b4b4;
Tff7b72const Te6edf3EK Tff7b72= Tb4b4b4{ Te6edf3CodeTff7b72:T79c0ff1Tb4b4b4, Te6edf3MessageTff7b72:T79c0ff2Tb4b4b4, Te6edf3NamespaceTff7b72:T79c0ff3Tb4b4b4, Te6edf3FieldTff7b72:T79c0ff4 Tb4b4b4}Tb4b4b4;
Tff7b72const Te6edf3RSSI_OFFSET Tff7b72= T79c0ff157Tb4b4b4;

T8b949e// ===== Legacy RNode KISS opcodes (Framing.h) — used by Node Config =====
Tff7b72const Te6edf3CMD_FREQUENCY Tff7b72= T79c0ff0x01Tb4b4b4;
Tff7b72const Te6edf3CMD_BANDWIDTH Tff7b72= T79c0ff0x02Tb4b4b4;
Tff7b72const Te6edf3CMD_TXPOWER Tff7b72= T79c0ff0x03Tb4b4b4;
Tff7b72const Te6edf3CMD_SF Tff7b72= T79c0ff0x04Tb4b4b4;
Tff7b72const Te6edf3CMD_CR Tff7b72= T79c0ff0x05Tb4b4b4;
Tff7b72const Te6edf3CMD_RADIO_STATE Tff7b72= T79c0ff0x06Tb4b4b4;
Tff7b72const Te6edf3CMD_RADIO_LOCK Tff7b72= T79c0ff0x07Tb4b4b4;
Tff7b72const Te6edf3CMD_DETECT Tff7b72= T79c0ff0x08Tb4b4b4;
Tff7b72const Te6edf3CMD_IMPLICIT Tff7b72= T79c0ff0x09Tb4b4b4;
Tff7b72const Te6edf3CMD_LEAVE Tff7b72= T79c0ff0x0ATb4b4b4;
Tff7b72const Te6edf3CMD_ST_ALOCK Tff7b72= T79c0ff0x0BTb4b4b4;
Tff7b72const Te6edf3CMD_LT_ALOCK Tff7b72= T79c0ff0x0CTb4b4b4;
Tff7b72const Te6edf3CMD_PROMISC Tff7b72= T79c0ff0x0ETb4b4b4;
Tff7b72const Te6edf3CMD_DISP_INT Tff7b72= T79c0ff0x45Tb4b4b4;
Tff7b72const Te6edf3CMD_BT_CTRL Tff7b72= T79c0ff0x46Tb4b4b4;
Tff7b72const Te6edf3CMD_BOARD Tff7b72= T79c0ff0x47Tb4b4b4;
Tff7b72const Te6edf3CMD_PLATFORM Tff7b72= T79c0ff0x48Tb4b4b4;
Tff7b72const Te6edf3CMD_MCU Tff7b72= T79c0ff0x49Tb4b4b4;
Tff7b72const Te6edf3CMD_FW_VERSION Tff7b72= T79c0ff0x50Tb4b4b4;
Tff7b72const Te6edf3CMD_ROM_READ Tff7b72= T79c0ff0x51Tb4b4b4;
Tff7b72const Te6edf3CMD_ROM_WRITE Tff7b72= T79c0ff0x52Tb4b4b4;
Tff7b72const Te6edf3CMD_CONF_SAVE Tff7b72= T79c0ff0x53Tb4b4b4;
Tff7b72const Te6edf3CMD_CONF_DELETE Tff7b72= T79c0ff0x54Tb4b4b4;
Tff7b72const Te6edf3CMD_DEV_HASH Tff7b72= T79c0ff0x56Tb4b4b4;
Tff7b72const Te6edf3CMD_DEV_SIG Tff7b72= T79c0ff0x57Tb4b4b4;
Tff7b72const Te6edf3CMD_FW_HASH Tff7b72= T79c0ff0x58Tb4b4b4;
Tff7b72const Te6edf3CMD_UNLOCK_ROM Tff7b72= T79c0ff0x59Tb4b4b4;
Tff7b72const Te6edf3ROM_UNLOCK_BYTE Tff7b72= T79c0ff0xF8Tb4b4b4;
Tff7b72const Te6edf3CMD_HASHES Tff7b72= T79c0ff0x60Tb4b4b4;
Tff7b72const Te6edf3CMD_BT_PIN Tff7b72= T79c0ff0x62Tb4b4b4;
Tff7b72const Te6edf3CMD_DISP_ADDR Tff7b72= T79c0ff0x63Tb4b4b4;
Tff7b72const Te6edf3CMD_DISP_BLNK Tff7b72= T79c0ff0x64Tb4b4b4;
Tff7b72const Te6edf3CMD_NP_INT Tff7b72= T79c0ff0x65Tb4b4b4;
Tff7b72const Te6edf3CMD_DISP_READ Tff7b72= T79c0ff0x66Tb4b4b4;
Tff7b72const Te6edf3CMD_DISP_ROT Tff7b72= T79c0ff0x67Tb4b4b4;
Tff7b72const Te6edf3CMD_DISP_RCND Tff7b72= T79c0ff0x68Tb4b4b4;
Tff7b72const Te6edf3CMD_DIS_IA Tff7b72= T79c0ff0x69Tb4b4b4;
Tff7b72const Te6edf3CMD_WIFI_MODE Tff7b72= T79c0ff0x6ATb4b4b4;
Tff7b72const Te6edf3CMD_WIFI_SSID Tff7b72= T79c0ff0x6BTb4b4b4;
Tff7b72const Te6edf3CMD_WIFI_PSK Tff7b72= T79c0ff0x6CTb4b4b4;
Tff7b72const Te6edf3CMD_CFG_READ Tff7b72= T79c0ff0x6DTb4b4b4;
Tff7b72const Te6edf3CMD_WIFI_CHN Tff7b72= T79c0ff0x6ETb4b4b4;
Tff7b72const Te6edf3CMD_BT_UNPAIR Tff7b72= T79c0ff0x70Tb4b4b4;
Tff7b72const Te6edf3CMD_WIFI_IP Tff7b72= T79c0ff0x84Tb4b4b4;
Tff7b72const Te6edf3CMD_WIFI_NM Tff7b72= T79c0ff0x85Tb4b4b4;
Tff7b72const Te6edf3DETECT_REQ Tff7b72= T79c0ff0x73Tb4b4b4;
Tff7b72const Te6edf3DETECT_RESP Tff7b72= T79c0ff0x46Tb4b4b4;

T8b949e// Decode tables for the read-only "Device Info" sub-tab (from Boards.h).
Tff7b72const Te6edf3PLATFORM_NAMES Tff7b72= Tb4b4b4{
T79c0ff0x60Tff7b72: Ta5d6ff'Native'Tb4b4b4, T79c0ff0x70Tff7b72: Ta5d6ff'nRF52'Tb4b4b4, T79c0ff0x80Tff7b72: Ta5d6ff'ESP32'Tb4b4b4, T79c0ff0x90Tff7b72: Ta5d6ff'AVR'Tb4b4b4,
Tb4b4b4}Tb4b4b4;
Tff7b72const Te6edf3MCU_NAMES Tff7b72= Tb4b4b4{
T79c0ff0x61Tff7b72: Ta5d6ff'Native'Tb4b4b4, T79c0ff0x71Tff7b72: Ta5d6ff'nRF52840'Tb4b4b4, T79c0ff0x81Tff7b72: Ta5d6ff'ESP32'Tb4b4b4, T79c0ff0x91Tff7b72: Ta5d6ff'ATmega1284P'Tb4b4b4, T79c0ff0x92Tff7b72: Ta5d6ff'ATmega2560'Tb4b4b4,
Tb4b4b4}Tb4b4b4;
Tff7b72const Te6edf3BOARD_NAMES Tff7b72= Tb4b4b4{
T79c0ff0x31Tff7b72:Ta5d6ff'RNode v1'Tb4b4b4, T79c0ff0x32Tff7b72:Ta5d6ff'HMBRW'Tb4b4b4, T79c0ff0x33Tff7b72:Ta5d6ff'TTGO T-Beam'Tb4b4b4, T79c0ff0x34Tff7b72:Ta5d6ff'Huzzah32'Tb4b4b4, T79c0ff0x35Tff7b72:Ta5d6ff'Generic ESP32'Tb4b4b4,
T79c0ff0x36Tff7b72:Ta5d6ff'TTGO LoRa32 v2.0'Tb4b4b4, T79c0ff0x37Tff7b72:Ta5d6ff'TTGO LoRa32 v2.1'Tb4b4b4, T79c0ff0x38Tff7b72:Ta5d6ff'Heltec LoRa32 v2'Tb4b4b4, T79c0ff0x39Tff7b72:Ta5d6ff'TTGO LoRa32 v1.0'Tb4b4b4,
T79c0ff0x3ATff7b72:Ta5d6ff'Heltec LoRa32 v3'Tb4b4b4, T79c0ff0x3BTff7b72:Ta5d6ff'LilyGO T-Deck'Tb4b4b4, T79c0ff0x3CTff7b72:Ta5d6ff'Heltec T114'Tb4b4b4, T79c0ff0x3DTff7b72:Ta5d6ff'T-Beam Supreme'Tb4b4b4,
T79c0ff0x3ETff7b72:Ta5d6ff'XIAO ESP32-S3'Tb4b4b4, T79c0ff0x3FTff7b72:Ta5d6ff'Heltec LoRa32 v4'Tb4b4b4, T79c0ff0x40Tff7b72:Ta5d6ff'RNode v2.0'Tb4b4b4, T79c0ff0x41Tff7b72:Ta5d6ff'RNode v2.1'Tb4b4b4,
T79c0ff0x42Tff7b72:Ta5d6ff'T3S3'Tb4b4b4, T79c0ff0x44Tff7b72:Ta5d6ff'LilyGO T-Echo'Tb4b4b4, T79c0ff0x50Tff7b72:Ta5d6ff'Generic nRF52'Tb4b4b4, T79c0ff0x51Tff7b72:Ta5d6ff'WisCore RAK4631'Tb4b4b4, T79c0ff0x60Tff7b72:Ta5d6ff'Native Linux'Tb4b4b4,
Tb4b4b4}Tb4b4b4;
T8b949e// CONF_OK marker indicating the device boots into TNC mode.
Tff7b72const Te6edf3CONF_OK_BYTE Tff7b72= T79c0ff0x73Tb4b4b4;

T8b949e// ===== Node Config static schema =====
T8b949e// Each section's fields share the shape Provisioning schema fields use (id, name, type,
T8b949e// flags, min/max, default), so buildFieldRow can render them. Extra keys carry the
T8b949e// wire-format details (`cmd`, `encoding`, `queryPayload`) the LegacyClient consumes.
Tff7b72const Te6edf3NCFG_ENC Tff7b72= Tb4b4b4{
T8b949e// Single-byte unsigned (0..255). Query payload: [0xFF] (firmware echoes current value).
Te6edf3u8Tff7b72: Tb4b4b4{ Te6edf3widthTff7b72: T79c0ff1Tb4b4b4, Te6edf3encTff7b72: Tb4b4b4(Te6edf3nTb4b4b4) Tb4b4b4=> Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[Te6edf3n Tff7b72& T79c0ff0xffTb4b4b4]Tb4b4b4)Tb4b4b4,
Te6edf3decTff7b72: Tb4b4b4(Te6edf3bTb4b4b4) Tb4b4b4=> Te6edf3bTb4b4b4.Te6edf3length Tff7b72>= T79c0ff1 Tff7b72? Te6edf3bTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72: Tff7b72nullTb4b4b4,
Te6edf3queryTff7b72: Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[T79c0ff0xFFTb4b4b4]Tb4b4b4) Tb4b4b4}Tb4b4b4,
T8b949e// Single-byte signed (-128..127). Used for TXP.
Te6edf3i8Tff7b72: Tb4b4b4{ Te6edf3widthTff7b72: T79c0ff1Tb4b4b4, Te6edf3encTff7b72: Tb4b4b4(Te6edf3nTb4b4b4) Tb4b4b4=> Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[Te6edf3n Tff7b72& T79c0ff0xffTb4b4b4]Tb4b4b4)Tb4b4b4,
Te6edf3decTff7b72: Tb4b4b4(Te6edf3bTb4b4b4) Tb4b4b4=> Te6edf3bTb4b4b4.Te6edf3length Tff7b72>= T79c0ff1 Tff7b72? Tb4b4b4(Te6edf3bTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72< T79c0ff128 Tff7b72? Te6edf3bTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72: Te6edf3bTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72- T79c0ff256Tb4b4b4) Tff7b72: Tff7b72nullTb4b4b4,
Te6edf3queryTff7b72: Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[T79c0ff0xFFTb4b4b4]Tb4b4b4) Tb4b4b4}Tb4b4b4,
T8b949e// 4-byte big-endian unsigned. Used for FREQ, BW. Query payload: 4 zero bytes.
Te6edf3be32Tff7b72: Tb4b4b4{ Te6edf3widthTff7b72: T79c0ff4Tb4b4b4, Te6edf3encTff7b72: Tb4b4b4(Te6edf3nTb4b4b4) Tb4b4b4=> Tb4b4b4{ Tff7b72const Te6edf3a Tff7b72= Tff7b72new Tffa657Uint8ArrayTb4b4b4(T79c0ff4Tb4b4b4)Tb4b4b4; Te6edf3aTb4b4b4[T79c0ff0Tb4b4b4]Tff7b72=Tb4b4b4(Te6edf3nTff7b72>>>T79c0ff24Tb4b4b4)Tff7b72&T79c0ff0xffTb4b4b4; Te6edf3aTb4b4b4[T79c0ff1Tb4b4b4]Tff7b72=Tb4b4b4(Te6edf3nTff7b72>>>T79c0ff16Tb4b4b4)Tff7b72&T79c0ff0xffTb4b4b4; Te6edf3aTb4b4b4[T79c0ff2Tb4b4b4]Tff7b72=Tb4b4b4(Te6edf3nTff7b72>>>T79c0ff8Tb4b4b4)Tff7b72&T79c0ff0xffTb4b4b4; Te6edf3aTb4b4b4[T79c0ff3Tb4b4b4]Tff7b72=Te6edf3nTff7b72&T79c0ff0xffTb4b4b4; Tff7b72return Te6edf3aTb4b4b4; Tb4b4b4}Tb4b4b4,
Te6edf3decTff7b72: Tb4b4b4(Te6edf3bTb4b4b4) Tb4b4b4=> Te6edf3bTb4b4b4.Te6edf3length Tff7b72>= T79c0ff4 Tff7b72? Tb4b4b4(Te6edf3bTb4b4b4[T79c0ff0Tb4b4b4]Tff7b72*T79c0ff0x1000000 Tff7b72+ Tb4b4b4(Tb4b4b4(Te6edf3bTb4b4b4[T79c0ff1Tb4b4b4]Tff7b72<<T79c0ff16Tb4b4b4)Tff7b72|Tb4b4b4(Te6edf3bTb4b4b4[T79c0ff2Tb4b4b4]Tff7b72<<T79c0ff8Tb4b4b4)Tff7b72|Te6edf3bTb4b4b4[T79c0ff3Tb4b4b4]Tb4b4b4)Tb4b4b4) Tff7b72: Tff7b72nullTb4b4b4,
Te6edf3queryTff7b72: Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tff7b72new Tffa657Uint8ArrayTb4b4b4(T79c0ff4Tb4b4b4) Tb4b4b4}Tb4b4b4,
T8b949e// Null-terminated UTF-8 string. Used for SSID, PSK.
Te6edf3strTff7b72: Tb4b4b4{ Te6edf3encStrTff7b72: Tb4b4b4(Te6edf3sTb4b4b4, Te6edf3maxLenTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3u Tff7b72= Tff7b72new Te6edf3TextEncoderTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3encodeTb4b4b4(Tffa657StringTb4b4b4(Te6edf3s Tff7b72|| Ta5d6ff''Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3len Tff7b72= Tffa657MathTb4b4b4.Te6edf3minTb4b4b4(Te6edf3uTb4b4b4.Te6edf3lengthTb4b4b4, Te6edf3maxLenTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3a Tff7b72= Tff7b72new Tffa657Uint8ArrayTb4b4b4(Te6edf3len Tff7b72+ T79c0ff1Tb4b4b4)Tb4b4b4;
Te6edf3aTb4b4b4.Te6edf3setTb4b4b4(Te6edf3uTb4b4b4.Te6edf3subarrayTb4b4b4(T79c0ff0Tb4b4b4, Te6edf3lenTb4b4b4)Tb4b4b4, T79c0ff0Tb4b4b4)Tb4b4b4;
Te6edf3aTb4b4b4[Te6edf3lenTb4b4b4] Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72return Te6edf3aTb4b4b4;
Tb4b4b4} Tb4b4b4}Tb4b4b4,
T8b949e// 4 octets (IPv4). Used for IP, NETMASK.
Te6edf3ip4Tff7b72: Tb4b4b4{ Te6edf3encTff7b72: Tb4b4b4(Te6edf3sTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3sTb4b4b4) Tff7b72return Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[T79c0ff0Tb4b4b4,T79c0ff0Tb4b4b4,T79c0ff0Tb4b4b4,T79c0ff0Tb4b4b4]Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3parts Tff7b72= Tffa657StringTb4b4b4(Te6edf3sTb4b4b4)Tb4b4b4.Te6edf3splitTb4b4b4(Ta5d6ff'.'Tb4b4b4)Tb4b4b4.Te6edf3mapTb4b4b4(Te6edf3p Tb4b4b4=> Tffa657parseIntTb4b4b4(Te6edf3pTb4b4b4, T79c0ff10Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3a Tff7b72= Tff7b72new Tffa657Uint8ArrayTb4b4b4(T79c0ff4Tb4b4b4)Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72let Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< T79c0ff4Tb4b4b4; Tff7b72++Te6edf3iTb4b4b4) Te6edf3aTb4b4b4[Te6edf3iTb4b4b4] Tff7b72= Tffa657NumberTb4b4b4.Tffa657isFiniteTb4b4b4(Te6edf3partsTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4) Tff7b72? Tb4b4b4(Te6edf3partsTb4b4b4[Te6edf3iTb4b4b4] Tff7b72& T79c0ff0xffTb4b4b4) Tff7b72: T79c0ff0Tb4b4b4;
Tff7b72return Te6edf3aTb4b4b4;
Tb4b4b4}Tb4b4b4,
Te6edf3decTff7b72: Tb4b4b4(Te6edf3bTb4b4b4) Tb4b4b4=> Te6edf3bTb4b4b4.Te6edf3length Tff7b72>= T79c0ff4 Tff7b72? Ta5d6ff`Tffd700${Te6edf3bTb4b4b4[T79c0ff0Tb4b4b4]Tffd700}Ta5d6ff.Tffd700${Te6edf3bTb4b4b4[T79c0ff1Tb4b4b4]Tffd700}Ta5d6ff.Tffd700${Te6edf3bTb4b4b4[T79c0ff2Tb4b4b4]Tffd700}Ta5d6ff.Tffd700${Te6edf3bTb4b4b4[T79c0ff3Tb4b4b4]Tffd700}Ta5d6ff` Tff7b72: Tff7b72null Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4;

T8b949e// FT.String/FT.Int sub-typed via `encoding` field. The LegacyClient picks
T8b949e// codec by name. `cmd` is the opcode to write (and usually to query).
Tff7b72const Te6edf3NODE_CONFIG_SCHEMA Tff7b72= Tb4b4b4{
Te6edf3device_infoTff7b72: Tb4b4b4{
Te6edf3labelTff7b72: Ta5d6ff'Device Info'Tb4b4b4,
Te6edf3customTff7b72: Ta5d6ff'device_info'Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Te6edf3radioTff7b72: Tb4b4b4{
Te6edf3labelTff7b72: Ta5d6ff'Radio'Tb4b4b4,
Te6edf3requiresRebootTff7b72: Tff7b72trueTb4b4b4,
Te6edf3customTff7b72: Ta5d6ff'radio'Tb4b4b4,
T8b949e// Custom panel combines the operating-mode selector (HOST/TNC) with the
T8b949e// radio params. Radio config only persists when boot-into-TNC is selected,
T8b949e// since in HOST mode the connected host re-issues radio params on every
T8b949e// boot and the EEPROM values are unused.
T8b949e// Fields defined here so the panel can iterate them via buildFieldRow.
Te6edf3fieldsTff7b72: Tb4b4b4[
Tb4b4b4{ Te6edf3idTff7b72: Ta5d6ff'frequency'Tb4b4b4, Te6edf3nameTff7b72: Ta5d6ff'frequency'Tb4b4b4, Te6edf3labelTff7b72: Ta5d6ff'Frequency'Tb4b4b4, Te6edf3typeTff7b72: Te6edf3FTTb4b4b4.Te6edf3IntTb4b4b4, Te6edf3encodingTff7b72: Ta5d6ff'be32'Tb4b4b4,
Te6edf3cmdTff7b72: Te6edf3CMD_FREQUENCYTb4b4b4, Te6edf3minITff7b72: T79c0ff100000000Tb4b4b4, Te6edf3maxITff7b72: T79c0ff1100000000Tb4b4b4, Te6edf3unitTff7b72: Ta5d6ff'Hz'Tb4b4b4, Tff7b72defaultTff7b72: T79c0ff0 Tb4b4b4}Tb4b4b4,
Tb4b4b4{ Te6edf3idTff7b72: Ta5d6ff'bandwidth'Tb4b4b4, Te6edf3nameTff7b72: Ta5d6ff'bandwidth'Tb4b4b4, Te6edf3labelTff7b72: Ta5d6ff'Bandwidth'Tb4b4b4, Te6edf3typeTff7b72: Te6edf3FTTb4b4b4.Te6edf3IntTb4b4b4, Te6edf3encodingTff7b72: Ta5d6ff'be32'Tb4b4b4,
Te6edf3cmdTff7b72: Te6edf3CMD_BANDWIDTHTb4b4b4, Te6edf3minITff7b72: T79c0ff7800Tb4b4b4, Te6edf3maxITff7b72: T79c0ff500000Tb4b4b4, Te6edf3unitTff7b72: Ta5d6ff'Hz'Tb4b4b4, Tff7b72defaultTff7b72: T79c0ff0 Tb4b4b4}Tb4b4b4,
Tb4b4b4{ Te6edf3idTff7b72: Ta5d6ff'sf'Tb4b4b4, Te6edf3nameTff7b72: Ta5d6ff'sf'Tb4b4b4, Te6edf3labelTff7b72: Ta5d6ff'Spreading factor'Tb4b4b4, Te6edf3typeTff7b72: Te6edf3FTTb4b4b4.Te6edf3IntTb4b4b4, Te6edf3encodingTff7b72: Ta5d6ff'u8'Tb4b4b4,
Te6edf3cmdTff7b72: Te6edf3CMD_SFTb4b4b4, Te6edf3minITff7b72: T79c0ff5Tb4b4b4, Te6edf3maxITff7b72: T79c0ff12Tb4b4b4, Tff7b72defaultTff7b72: T79c0ff0 Tb4b4b4}Tb4b4b4,
Tb4b4b4{ Te6edf3idTff7b72: Ta5d6ff'cr'Tb4b4b4, Te6edf3nameTff7b72: Ta5d6ff'cr'Tb4b4b4, Te6edf3labelTff7b72: Ta5d6ff'Coding rate'Tb4b4b4, Te6edf3typeTff7b72: Te6edf3FTTb4b4b4.Te6edf3IntTb4b4b4, Te6edf3encodingTff7b72: Ta5d6ff'u8'Tb4b4b4,
Te6edf3cmdTff7b72: Te6edf3CMD_CRTb4b4b4, Te6edf3minITff7b72: T79c0ff5Tb4b4b4, Te6edf3maxITff7b72: T79c0ff8Tb4b4b4, Tff7b72defaultTff7b72: T79c0ff5 Tb4b4b4}Tb4b4b4,
Tb4b4b4{ Te6edf3idTff7b72: Ta5d6ff'txp'Tb4b4b4, Te6edf3nameTff7b72: Ta5d6ff'txp'Tb4b4b4, Te6edf3labelTff7b72: Ta5d6ff'TX power'Tb4b4b4, Te6edf3typeTff7b72: Te6edf3FTTb4b4b4.Te6edf3IntTb4b4b4, Te6edf3encodingTff7b72: Ta5d6ff'i8'Tb4b4b4,
Te6edf3cmdTff7b72: Te6edf3CMD_TXPOWERTb4b4b4, Te6edf3minITff7b72: Tff7b72-T79c0ff9Tb4b4b4, Te6edf3maxITff7b72: T79c0ff22Tb4b4b4, Te6edf3unitTff7b72: Ta5d6ff'dBm'Tb4b4b4, Tff7b72defaultTff7b72: T79c0ff0 Tb4b4b4}Tb4b4b4,
T8b949e// CMD_DIS_IA: firmware byte 0x00 = IA enabled, 0x01 = IA disabled.
T8b949e// Exposed as a positive "Interference avoidance" toggle and inverted at
T8b949e// the wire. Set-only on the wire (no read counterpart), so the badge in
T8b949e// the row makes that clear — the rest of the Radio fields stay readable.
Tb4b4b4{ Te6edf3idTff7b72: Ta5d6ff'ia'Tb4b4b4, Te6edf3nameTff7b72: Ta5d6ff'ia'Tb4b4b4, Te6edf3labelTff7b72: Ta5d6ff'Interference avoidance'Tb4b4b4, Te6edf3typeTff7b72: Te6edf3FTTb4b4b4.Te6edf3BoolTb4b4b4,
Te6edf3cmdTff7b72: Te6edf3CMD_DIS_IATb4b4b4, Te6edf3encodingTff7b72: Ta5d6ff'u8'Tb4b4b4,
Te6edf3toWireTff7b72: Tb4b4b4(Te6edf3vTb4b4b4) Tb4b4b4=> Te6edf3v Tff7b72? T79c0ff0x00 Tff7b72: T79c0ff0x01Tb4b4b4, Te6edf3fromWireTff7b72: Tb4b4b4(Te6edf3bTb4b4b4) Tb4b4b4=> Te6edf3b Tff7b72=== T79c0ff0x00Tb4b4b4,
Tff7b72defaultTff7b72: Tff7b72falseTb4b4b4, Te6edf3readableTff7b72: Tff7b72false Tb4b4b4}Tb4b4b4,
Tb4b4b4]Tb4b4b4,
Te6edf3saveOrderTff7b72: Tb4b4b4[Ta5d6ff'frequency'Tb4b4b4,Ta5d6ff'bandwidth'Tb4b4b4,Ta5d6ff'sf'Tb4b4b4,Ta5d6ff'cr'Tb4b4b4,Ta5d6ff'txp'Tb4b4b4,Ta5d6ff'ia'Tb4b4b4]Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Te6edf3bluetoothTff7b72: Tb4b4b4{
Te6edf3labelTff7b72: Ta5d6ff'Bluetooth'Tb4b4b4,
Te6edf3customTff7b72: Ta5d6ff'bluetooth'Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Te6edf3wifiTff7b72: Tb4b4b4{
Te6edf3labelTff7b72: Ta5d6ff'WiFi'Tb4b4b4,
Te6edf3requiresRebootTff7b72: Tff7b72trueTb4b4b4,
Te6edf3fieldsTff7b72: Tb4b4b4[
Tb4b4b4{ Te6edf3idTff7b72: Ta5d6ff'mode'Tb4b4b4, Te6edf3nameTff7b72: Ta5d6ff'mode'Tb4b4b4, Te6edf3labelTff7b72: Ta5d6ff'Mode'Tb4b4b4, Te6edf3typeTff7b72: Te6edf3FTTb4b4b4.Te6edf3EnumTb4b4b4,
Te6edf3cmdTff7b72: Te6edf3CMD_WIFI_MODETb4b4b4, Te6edf3encodingTff7b72: Ta5d6ff'u8'Tb4b4b4,
Te6edf3enumValuesTff7b72: Tb4b4b4[T79c0ff0x00Tb4b4b4, T79c0ff0x01Tb4b4b4, T79c0ff0x02Tb4b4b4]Tb4b4b4, Te6edf3enumLabelsTff7b72: Tb4b4b4[Ta5d6ff'Off'Tb4b4b4, Ta5d6ff'Station'Tb4b4b4, Ta5d6ff'Access Point'Tb4b4b4]Tb4b4b4,
Tff7b72defaultTff7b72: T79c0ff0x00Tb4b4b4, Te6edf3readableTff7b72: Tff7b72false Tb4b4b4}Tb4b4b4,
Tb4b4b4{ Te6edf3idTff7b72: Ta5d6ff'channel'Tb4b4b4, Te6edf3nameTff7b72: Ta5d6ff'channel'Tb4b4b4, Te6edf3labelTff7b72: Ta5d6ff'Channel'Tb4b4b4, Te6edf3typeTff7b72: Te6edf3FTTb4b4b4.Te6edf3IntTb4b4b4, Te6edf3encodingTff7b72: Ta5d6ff'u8'Tb4b4b4,
Te6edf3cmdTff7b72: Te6edf3CMD_WIFI_CHNTb4b4b4, Te6edf3minITff7b72: T79c0ff1Tb4b4b4, Te6edf3maxITff7b72: T79c0ff13Tb4b4b4, Tff7b72defaultTff7b72: T79c0ff1Tb4b4b4, Te6edf3readableTff7b72: Tff7b72false Tb4b4b4}Tb4b4b4,
Tb4b4b4{ Te6edf3idTff7b72: Ta5d6ff'ssid'Tb4b4b4, Te6edf3nameTff7b72: Ta5d6ff'ssid'Tb4b4b4, Te6edf3labelTff7b72: Ta5d6ff'SSID'Tb4b4b4, Te6edf3typeTff7b72: Te6edf3FTTb4b4b4.Tffa657StringTb4b4b4, Te6edf3encodingTff7b72: Ta5d6ff'str'Tb4b4b4,
Te6edf3cmdTff7b72: Te6edf3CMD_WIFI_SSIDTb4b4b4, Te6edf3maxLenTff7b72: T79c0ff32Tb4b4b4, Tff7b72defaultTff7b72: Ta5d6ff''Tb4b4b4, Te6edf3readableTff7b72: Tff7b72false Tb4b4b4}Tb4b4b4,
Tb4b4b4{ Te6edf3idTff7b72: Ta5d6ff'psk'Tb4b4b4, Te6edf3nameTff7b72: Ta5d6ff'psk'Tb4b4b4, Te6edf3labelTff7b72: Ta5d6ff'PSK'Tb4b4b4, Te6edf3typeTff7b72: Te6edf3FTTb4b4b4.Tffa657StringTb4b4b4, Te6edf3encodingTff7b72: Ta5d6ff'str'Tb4b4b4,
Te6edf3cmdTff7b72: Te6edf3CMD_WIFI_PSKTb4b4b4, Te6edf3maxLenTff7b72: T79c0ff32Tb4b4b4, Tff7b72defaultTff7b72: Ta5d6ff''Tb4b4b4, Te6edf3flagsTff7b72: Te6edf3FFTb4b4b4.Te6edf3SECRETTb4b4b4, Te6edf3readableTff7b72: Tff7b72false Tb4b4b4}Tb4b4b4,
Tb4b4b4{ Te6edf3idTff7b72: Ta5d6ff'ip'Tb4b4b4, Te6edf3nameTff7b72: Ta5d6ff'ip'Tb4b4b4, Te6edf3labelTff7b72: Ta5d6ff'Static IP (0.0.0.0 = DHCP)'Tb4b4b4, Te6edf3typeTff7b72: Te6edf3FTTb4b4b4.Tffa657StringTb4b4b4, Te6edf3encodingTff7b72: Ta5d6ff'ip4'Tb4b4b4,
Te6edf3cmdTff7b72: Te6edf3CMD_WIFI_IPTb4b4b4, Tff7b72defaultTff7b72: Ta5d6ff'0.0.0.0'Tb4b4b4, Te6edf3readableTff7b72: Tff7b72false Tb4b4b4}Tb4b4b4,
Tb4b4b4{ Te6edf3idTff7b72: Ta5d6ff'nm'Tb4b4b4, Te6edf3nameTff7b72: Ta5d6ff'nm'Tb4b4b4, Te6edf3labelTff7b72: Ta5d6ff'Netmask'Tb4b4b4, Te6edf3typeTff7b72: Te6edf3FTTb4b4b4.Tffa657StringTb4b4b4, Te6edf3encodingTff7b72: Ta5d6ff'ip4'Tb4b4b4,
Te6edf3cmdTff7b72: Te6edf3CMD_WIFI_NMTb4b4b4, Tff7b72defaultTff7b72: Ta5d6ff'0.0.0.0'Tb4b4b4, Te6edf3readableTff7b72: Tff7b72false Tb4b4b4}Tb4b4b4,
Tb4b4b4]Tb4b4b4,
Te6edf3saveOrderTff7b72: Tb4b4b4[Ta5d6ff'mode'Tb4b4b4,Ta5d6ff'channel'Tb4b4b4,Ta5d6ff'ssid'Tb4b4b4,Ta5d6ff'psk'Tb4b4b4,Ta5d6ff'ip'Tb4b4b4,Ta5d6ff'nm'Tb4b4b4]Tb4b4b4,
Te6edf3saveTrailerNoteTff7b72: Ta5d6ff'Settings are written to the WiFi config sector and take effect on the next reboot.'Tb4b4b4,
T8b949e// CMD_WIFI_* opcodes are write-only in the firmware — there's no read
T8b949e// counterpart and we won't decode raw EEPROM at hardcoded offsets. Fields
T8b949e// surface as "set-only" in the UI (per-field badge + section banner);
T8b949e// edits write to the device but values can't be read back.
Tb4b4b4}Tb4b4b4,
Te6edf3displayTff7b72: Tb4b4b4{
Te6edf3labelTff7b72: Ta5d6ff'Display'Tb4b4b4,
Te6edf3fieldsTff7b72: Tb4b4b4[
Tb4b4b4{ Te6edf3idTff7b72: Ta5d6ff'intensity'Tb4b4b4, Te6edf3nameTff7b72: Ta5d6ff'intensity'Tb4b4b4, Te6edf3labelTff7b72: Ta5d6ff'Display intensity'Tb4b4b4, Te6edf3typeTff7b72: Te6edf3FTTb4b4b4.Te6edf3IntTb4b4b4, Te6edf3encodingTff7b72: Ta5d6ff'u8'Tb4b4b4,
Te6edf3cmdTff7b72: Te6edf3CMD_DISP_INTTb4b4b4, Te6edf3minITff7b72: T79c0ff0Tb4b4b4, Te6edf3maxITff7b72: T79c0ff255Tb4b4b4, Tff7b72defaultTff7b72: T79c0ff0Tb4b4b4, Te6edf3readableTff7b72: Tff7b72false Tb4b4b4}Tb4b4b4,
Tb4b4b4{ Te6edf3idTff7b72: Ta5d6ff'blanking'Tb4b4b4, Te6edf3nameTff7b72: Ta5d6ff'blanking'Tb4b4b4, Te6edf3labelTff7b72: Ta5d6ff'Blanking timeout (s, 0=off)'Tb4b4b4, Te6edf3typeTff7b72: Te6edf3FTTb4b4b4.Te6edf3IntTb4b4b4, Te6edf3encodingTff7b72: Ta5d6ff'u8'Tb4b4b4,
Te6edf3cmdTff7b72: Te6edf3CMD_DISP_BLNKTb4b4b4, Te6edf3minITff7b72: T79c0ff0Tb4b4b4, Te6edf3maxITff7b72: T79c0ff255Tb4b4b4, Tff7b72defaultTff7b72: T79c0ff0Tb4b4b4, Te6edf3readableTff7b72: Tff7b72false Tb4b4b4}Tb4b4b4,
Tb4b4b4{ Te6edf3idTff7b72: Ta5d6ff'rotation'Tb4b4b4, Te6edf3nameTff7b72: Ta5d6ff'rotation'Tb4b4b4, Te6edf3labelTff7b72: Ta5d6ff'Rotation'Tb4b4b4, Te6edf3typeTff7b72: Te6edf3FTTb4b4b4.Te6edf3EnumTb4b4b4,
Te6edf3cmdTff7b72: Te6edf3CMD_DISP_ROTTb4b4b4, Te6edf3encodingTff7b72: Ta5d6ff'u8'Tb4b4b4,
Te6edf3enumValuesTff7b72: Tb4b4b4[T79c0ff0Tb4b4b4, T79c0ff1Tb4b4b4, T79c0ff2Tb4b4b4, T79c0ff3Tb4b4b4]Tb4b4b4, Te6edf3enumLabelsTff7b72: Tb4b4b4[Ta5d6ff'0°'Tb4b4b4, Ta5d6ff'90°'Tb4b4b4, Ta5d6ff'180°'Tb4b4b4, Ta5d6ff'270°'Tb4b4b4]Tb4b4b4,
Tff7b72defaultTff7b72: T79c0ff0Tb4b4b4, Te6edf3readableTff7b72: Tff7b72false Tb4b4b4}Tb4b4b4,
Tb4b4b4{ Te6edf3idTff7b72: Ta5d6ff'addr'Tb4b4b4, Te6edf3nameTff7b72: Ta5d6ff'addr'Tb4b4b4, Te6edf3labelTff7b72: Ta5d6ff'I2C address'Tb4b4b4, Te6edf3typeTff7b72: Te6edf3FTTb4b4b4.Te6edf3IntTb4b4b4, Te6edf3encodingTff7b72: Ta5d6ff'u8'Tb4b4b4,
Te6edf3cmdTff7b72: Te6edf3CMD_DISP_ADDRTb4b4b4, Te6edf3minITff7b72: T79c0ff0Tb4b4b4, Te6edf3maxITff7b72: T79c0ff255Tb4b4b4, Tff7b72defaultTff7b72: T79c0ff0x3CTb4b4b4, Te6edf3readableTff7b72: Tff7b72false Tb4b4b4}Tb4b4b4,
Tb4b4b4{ Te6edf3idTff7b72: Ta5d6ff'np'Tb4b4b4, Te6edf3nameTff7b72: Ta5d6ff'np'Tb4b4b4, Te6edf3labelTff7b72: Ta5d6ff'NeoPixel intensity'Tb4b4b4, Te6edf3typeTff7b72: Te6edf3FTTb4b4b4.Te6edf3IntTb4b4b4, Te6edf3encodingTff7b72: Ta5d6ff'u8'Tb4b4b4,
Te6edf3cmdTff7b72: Te6edf3CMD_NP_INTTb4b4b4, Te6edf3minITff7b72: T79c0ff0Tb4b4b4, Te6edf3maxITff7b72: T79c0ff255Tb4b4b4, Tff7b72defaultTff7b72: T79c0ff0Tb4b4b4, Te6edf3readableTff7b72: Tff7b72false Tb4b4b4}Tb4b4b4,
Tb4b4b4]Tb4b4b4,
Te6edf3saveOrderTff7b72: Tb4b4b4[Ta5d6ff'intensity'Tb4b4b4,Ta5d6ff'blanking'Tb4b4b4,Ta5d6ff'rotation'Tb4b4b4,Ta5d6ff'addr'Tb4b4b4,Ta5d6ff'np'Tb4b4b4]Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Te6edf3eepromTff7b72: Tb4b4b4{
Te6edf3labelTff7b72: Ta5d6ff'EEPROM'Tb4b4b4,
Te6edf3customTff7b72: Ta5d6ff'eeprom'Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4;

T8b949e// ===== MsgPack =====
Tff7b72class Te6edf3Packer Tb4b4b4{
Tff7b72constructorTb4b4b4(Tb4b4b4)Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3bufsTff7b72=Tb4b4b4[Tb4b4b4]Tb4b4b4; Tff7b72thisTb4b4b4.Te6edf3sizeTff7b72=T79c0ff0Tb4b4b4; Tb4b4b4}
Te6edf3_pushTb4b4b4(Te6edf3aTb4b4b4)Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3bufsTb4b4b4.Te6edf3pushTb4b4b4(Te6edf3aTb4b4b4)Tb4b4b4; Tff7b72thisTb4b4b4.Te6edf3sizeTff7b72+=Te6edf3aTb4b4b4.Te6edf3lengthTb4b4b4; Tb4b4b4}
Te6edf3_w8Tb4b4b4(Te6edf3nTb4b4b4)Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3_pushTb4b4b4(Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[Te6edf3nTff7b72&T79c0ff0xffTb4b4b4]Tb4b4b4)Tb4b4b4)Tb4b4b4; Tb4b4b4}
Te6edf3_w16Tb4b4b4(Te6edf3nTb4b4b4)Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3_pushTb4b4b4(Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[Tb4b4b4(Te6edf3nTff7b72>>T79c0ff8Tb4b4b4)Tff7b72&T79c0ff0xffTb4b4b4,Te6edf3nTff7b72&T79c0ff0xffTb4b4b4]Tb4b4b4)Tb4b4b4)Tb4b4b4; Tb4b4b4}
Te6edf3_w32Tb4b4b4(Te6edf3nTb4b4b4)Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3_pushTb4b4b4(Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[Tb4b4b4(Te6edf3nTff7b72>>>T79c0ff24Tb4b4b4)Tff7b72&T79c0ff0xffTb4b4b4,Tb4b4b4(Te6edf3nTff7b72>>>T79c0ff16Tb4b4b4)Tff7b72&T79c0ff0xffTb4b4b4,Tb4b4b4(Te6edf3nTff7b72>>>T79c0ff8Tb4b4b4)Tff7b72&T79c0ff0xffTb4b4b4,Te6edf3nTff7b72&T79c0ff0xffTb4b4b4]Tb4b4b4)Tb4b4b4)Tb4b4b4; Tb4b4b4}
Te6edf3_w64Tb4b4b4(Te6edf3bigTb4b4b4)Tb4b4b4{ Tff7b72const Te6edf3aTff7b72=Tff7b72new Tffa657Uint8ArrayTb4b4b4(T79c0ff8Tb4b4b4)Tb4b4b4; Tff7b72forTb4b4b4(Tff7b72let Te6edf3iTff7b72=T79c0ff7Tb4b4b4;Te6edf3iTff7b72>=T79c0ff0Tb4b4b4;Tff7b72--Te6edf3iTb4b4b4)Tb4b4b4{Te6edf3aTb4b4b4[Te6edf3iTb4b4b4]Tff7b72=Tffa657NumberTb4b4b4(Te6edf3bigTff7b72&T79c0ff0xffnTb4b4b4)Tb4b4b4;Te6edf3bigTff7b72>>=T79c0ff8nTb4b4b4;Tb4b4b4} Tff7b72thisTb4b4b4.Te6edf3_pushTb4b4b4(Te6edf3aTb4b4b4)Tb4b4b4; Tb4b4b4}
Te6edf3nilTb4b4b4(Tb4b4b4)Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3_w8Tb4b4b4(T79c0ff0xc0Tb4b4b4)Tb4b4b4; Tb4b4b4}
Te6edf3boolTb4b4b4(Te6edf3bTb4b4b4)Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3_w8Tb4b4b4(Te6edf3bTff7b72?T79c0ff0xc3Tff7b72:T79c0ff0xc2Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72intTb4b4b4(Te6edf3nTb4b4b4)Tb4b4b4{
Tff7b72let Te6edf3bn Tff7b72= Tff7b72typeof Te6edf3nTff7b72===Ta5d6ff'bigint' Tff7b72? Te6edf3n Tff7b72: Tffa657BigIntTb4b4b4(Tffa657MathTb4b4b4.Te6edf3truncTb4b4b4(Tffa657NumberTb4b4b4(Te6edf3nTb4b4b4)Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3bnTff7b72>=T79c0ff0nTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3bnTff7b72<T79c0ff128nTb4b4b4) Tff7b72thisTb4b4b4.Te6edf3_w8Tb4b4b4(Tffa657NumberTb4b4b4(Te6edf3bnTb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72else Tff7b72if Tb4b4b4(Te6edf3bnTff7b72<T79c0ff256nTb4b4b4) Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3_w8Tb4b4b4(T79c0ff0xccTb4b4b4)Tb4b4b4; Tff7b72thisTb4b4b4.Te6edf3_w8Tb4b4b4(Tffa657NumberTb4b4b4(Te6edf3bnTb4b4b4)Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72else Tff7b72if Tb4b4b4(Te6edf3bnTff7b72<T79c0ff65536nTb4b4b4) Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3_w8Tb4b4b4(T79c0ff0xcdTb4b4b4)Tb4b4b4; Tff7b72thisTb4b4b4.Te6edf3_w16Tb4b4b4(Tffa657NumberTb4b4b4(Te6edf3bnTb4b4b4)Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72else Tff7b72if Tb4b4b4(Te6edf3bnTff7b72<T79c0ff4294967296nTb4b4b4) Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3_w8Tb4b4b4(T79c0ff0xceTb4b4b4)Tb4b4b4; Tff7b72thisTb4b4b4.Te6edf3_w32Tb4b4b4(Tffa657NumberTb4b4b4(Te6edf3bnTb4b4b4)Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72else Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3_w8Tb4b4b4(T79c0ff0xcfTb4b4b4)Tb4b4b4; Tff7b72thisTb4b4b4.Te6edf3_w64Tb4b4b4(Te6edf3bnTb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3bnTff7b72>=Tff7b72-T79c0ff32nTb4b4b4) Tff7b72thisTb4b4b4.Te6edf3_w8Tb4b4b4(Tffa657NumberTb4b4b4(Te6edf3bnTb4b4b4)Tff7b72&T79c0ff0xffTb4b4b4)Tb4b4b4;
Tff7b72else Tff7b72if Tb4b4b4(Te6edf3bnTff7b72>=Tff7b72-T79c0ff128nTb4b4b4) Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3_w8Tb4b4b4(T79c0ff0xd0Tb4b4b4)Tb4b4b4; Tff7b72thisTb4b4b4.Te6edf3_w8Tb4b4b4(Tffa657NumberTb4b4b4(Te6edf3bnTb4b4b4)Tff7b72&T79c0ff0xffTb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72else Tff7b72if Tb4b4b4(Te6edf3bnTff7b72>=Tff7b72-T79c0ff32768nTb4b4b4) Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3_w8Tb4b4b4(T79c0ff0xd1Tb4b4b4)Tb4b4b4; Tff7b72thisTb4b4b4.Te6edf3_w16Tb4b4b4(Tffa657NumberTb4b4b4(Te6edf3bnTb4b4b4)Tff7b72&T79c0ff0xffffTb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72else Tff7b72if Tb4b4b4(Te6edf3bnTff7b72>=Tff7b72-T79c0ff2147483648nTb4b4b4) Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3_w8Tb4b4b4(T79c0ff0xd2Tb4b4b4)Tb4b4b4; Tff7b72thisTb4b4b4.Te6edf3_w32Tb4b4b4(Tffa657NumberTb4b4b4(Te6edf3bnTb4b4b4)Tff7b72>>>T79c0ff0Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72else Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3_w8Tb4b4b4(T79c0ff0xd3Tb4b4b4)Tb4b4b4; Tff7b72thisTb4b4b4.Te6edf3_w64Tb4b4b4(Te6edf3bn Tff7b72+ Tb4b4b4(T79c0ff1nTff7b72<<T79c0ff64nTb4b4b4)Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72floatTb4b4b4(Te6edf3fTb4b4b4)Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3_w8Tb4b4b4(T79c0ff0xcbTb4b4b4)Tb4b4b4; Tff7b72const Te6edf3dvTff7b72=Tff7b72new Tffa657DataViewTb4b4b4(Tff7b72new Tffa657ArrayBufferTb4b4b4(T79c0ff8Tb4b4b4)Tb4b4b4)Tb4b4b4; Te6edf3dvTb4b4b4.Te6edf3setFloat64Tb4b4b4(T79c0ff0Tb4b4b4,Te6edf3fTb4b4b4,Tff7b72falseTb4b4b4)Tb4b4b4; Tff7b72thisTb4b4b4.Te6edf3_pushTb4b4b4(Tff7b72new Tffa657Uint8ArrayTb4b4b4(Te6edf3dvTb4b4b4.Te6edf3bufferTb4b4b4)Tb4b4b4)Tb4b4b4; Tb4b4b4}
Te6edf3strTb4b4b4(Te6edf3sTb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3bTff7b72=Tff7b72new Te6edf3TextEncoderTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3encodeTb4b4b4(Te6edf3sTb4b4b4)Tb4b4b4; Tff7b72const Te6edf3nTff7b72=Te6edf3bTb4b4b4.Te6edf3lengthTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3nTff7b72<T79c0ff32Tb4b4b4) Tff7b72thisTb4b4b4.Te6edf3_w8Tb4b4b4(T79c0ff0xa0Tff7b72|Te6edf3nTb4b4b4)Tb4b4b4;
Tff7b72else Tff7b72if Tb4b4b4(Te6edf3nTff7b72<T79c0ff256Tb4b4b4) Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3_w8Tb4b4b4(T79c0ff0xd9Tb4b4b4)Tb4b4b4; Tff7b72thisTb4b4b4.Te6edf3_w8Tb4b4b4(Te6edf3nTb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72else Tff7b72if Tb4b4b4(Te6edf3nTff7b72<T79c0ff65536Tb4b4b4) Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3_w8Tb4b4b4(T79c0ff0xdaTb4b4b4)Tb4b4b4; Tff7b72thisTb4b4b4.Te6edf3_w16Tb4b4b4(Te6edf3nTb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72else Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3_w8Tb4b4b4(T79c0ff0xdbTb4b4b4)Tb4b4b4; Tff7b72thisTb4b4b4.Te6edf3_w32Tb4b4b4(Te6edf3nTb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72thisTb4b4b4.Te6edf3_pushTb4b4b4(Te6edf3bTb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3binTb4b4b4(Te6edf3bTb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3nTff7b72=Te6edf3bTb4b4b4.Te6edf3lengthTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3nTff7b72<T79c0ff256Tb4b4b4) Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3_w8Tb4b4b4(T79c0ff0xc4Tb4b4b4)Tb4b4b4; Tff7b72thisTb4b4b4.Te6edf3_w8Tb4b4b4(Te6edf3nTb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72else Tff7b72if Tb4b4b4(Te6edf3nTff7b72<T79c0ff65536Tb4b4b4) Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3_w8Tb4b4b4(T79c0ff0xc5Tb4b4b4)Tb4b4b4; Tff7b72thisTb4b4b4.Te6edf3_w16Tb4b4b4(Te6edf3nTb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72else Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3_w8Tb4b4b4(T79c0ff0xc6Tb4b4b4)Tb4b4b4; Tff7b72thisTb4b4b4.Te6edf3_w32Tb4b4b4(Te6edf3nTb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72thisTb4b4b4.Te6edf3_pushTb4b4b4(Te6edf3b Tff7b72instanceof Tffa657Uint8Array Tff7b72? Te6edf3b Tff7b72: Tff7b72new Tffa657Uint8ArrayTb4b4b4(Te6edf3bTb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3arrTb4b4b4(Te6edf3nTb4b4b4)Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3nTff7b72<T79c0ff16Tb4b4b4) Tff7b72thisTb4b4b4.Te6edf3_w8Tb4b4b4(T79c0ff0x90Tff7b72|Te6edf3nTb4b4b4)Tb4b4b4;
Tff7b72else Tff7b72if Tb4b4b4(Te6edf3nTff7b72<T79c0ff65536Tb4b4b4) Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3_w8Tb4b4b4(T79c0ff0xdcTb4b4b4)Tb4b4b4; Tff7b72thisTb4b4b4.Te6edf3_w16Tb4b4b4(Te6edf3nTb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72else Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3_w8Tb4b4b4(T79c0ff0xddTb4b4b4)Tb4b4b4; Tff7b72thisTb4b4b4.Te6edf3_w32Tb4b4b4(Te6edf3nTb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4}
Te6edf3mapTb4b4b4(Te6edf3nTb4b4b4)Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3nTff7b72<T79c0ff16Tb4b4b4) Tff7b72thisTb4b4b4.Te6edf3_w8Tb4b4b4(T79c0ff0x80Tff7b72|Te6edf3nTb4b4b4)Tb4b4b4;
Tff7b72else Tff7b72if Tb4b4b4(Te6edf3nTff7b72<T79c0ff65536Tb4b4b4) Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3_w8Tb4b4b4(T79c0ff0xdeTb4b4b4)Tb4b4b4; Tff7b72thisTb4b4b4.Te6edf3_w16Tb4b4b4(Te6edf3nTb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72else Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3_w8Tb4b4b4(T79c0ff0xdfTb4b4b4)Tb4b4b4; Tff7b72thisTb4b4b4.Te6edf3_w32Tb4b4b4(Te6edf3nTb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4}
Te6edf3resultTb4b4b4(Tb4b4b4)Tb4b4b4{ Tff7b72const Te6edf3outTff7b72=Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tff7b72thisTb4b4b4.Te6edf3sizeTb4b4b4)Tb4b4b4; Tff7b72let Te6edf3oTff7b72=T79c0ff0Tb4b4b4; Tff7b72forTb4b4b4(Tff7b72const Te6edf3b Tff7b72of Tff7b72thisTb4b4b4.Te6edf3bufsTb4b4b4)Tb4b4b4{ Te6edf3outTb4b4b4.Te6edf3setTb4b4b4(Te6edf3bTb4b4b4,Te6edf3oTb4b4b4)Tb4b4b4; Te6edf3oTff7b72+=Te6edf3bTb4b4b4.Te6edf3lengthTb4b4b4; Tb4b4b4} Tff7b72return Te6edf3outTb4b4b4; Tb4b4b4}
Tb4b4b4}
Tff7b72class Te6edf3Unpacker Tb4b4b4{
Tff7b72constructorTb4b4b4(Te6edf3u8Tb4b4b4)Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3bTff7b72=Te6edf3u8Tb4b4b4; Tff7b72thisTb4b4b4.Te6edf3pTff7b72=T79c0ff0Tb4b4b4; Tff7b72thisTb4b4b4.Te6edf3decTff7b72=Tff7b72new Te6edf3TextDecoderTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4}
Te6edf3_r8Tb4b4b4(Tb4b4b4)Tb4b4b4{ Tff7b72return Tff7b72thisTb4b4b4.Te6edf3bTb4b4b4[Tff7b72thisTb4b4b4.Te6edf3pTff7b72++Tb4b4b4]Tb4b4b4; Tb4b4b4}
Te6edf3_r16Tb4b4b4(Tb4b4b4)Tb4b4b4{ Tff7b72const Te6edf3vTff7b72=Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3bTb4b4b4[Tff7b72thisTb4b4b4.Te6edf3pTb4b4b4]Tff7b72<<T79c0ff8Tb4b4b4)Tff7b72|Tff7b72thisTb4b4b4.Te6edf3bTb4b4b4[Tff7b72thisTb4b4b4.Te6edf3pTff7b72+T79c0ff1Tb4b4b4]Tb4b4b4; Tff7b72thisTb4b4b4.Te6edf3pTff7b72+=T79c0ff2Tb4b4b4; Tff7b72return Te6edf3vTff7b72>>>T79c0ff0Tb4b4b4; Tb4b4b4}
Te6edf3_r32Tb4b4b4(Tb4b4b4)Tb4b4b4{ Tff7b72const Te6edf3vTff7b72=Tff7b72thisTb4b4b4.Te6edf3bTb4b4b4[Tff7b72thisTb4b4b4.Te6edf3pTb4b4b4]Tff7b72*T79c0ff0x1000000 Tff7b72+ Tb4b4b4(Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3bTb4b4b4[Tff7b72thisTb4b4b4.Te6edf3pTff7b72+T79c0ff1Tb4b4b4]Tff7b72<<T79c0ff16Tb4b4b4)Tff7b72|Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3bTb4b4b4[Tff7b72thisTb4b4b4.Te6edf3pTff7b72+T79c0ff2Tb4b4b4]Tff7b72<<T79c0ff8Tb4b4b4)Tff7b72|Tff7b72thisTb4b4b4.Te6edf3bTb4b4b4[Tff7b72thisTb4b4b4.Te6edf3pTff7b72+T79c0ff3Tb4b4b4]Tb4b4b4)Tb4b4b4; Tff7b72thisTb4b4b4.Te6edf3pTff7b72+=T79c0ff4Tb4b4b4; Tff7b72return Te6edf3vTb4b4b4; Tb4b4b4}
Te6edf3_r64uTb4b4b4(Tb4b4b4)Tb4b4b4{ Tff7b72let Te6edf3vTff7b72=T79c0ff0nTb4b4b4; Tff7b72forTb4b4b4(Tff7b72let Te6edf3iTff7b72=T79c0ff0Tb4b4b4;Te6edf3iTff7b72<T79c0ff8Tb4b4b4;Tff7b72++Te6edf3iTb4b4b4)Tb4b4b4{ Te6edf3vTff7b72=Tb4b4b4(Te6edf3vTff7b72<<T79c0ff8nTb4b4b4)Tff7b72|Tffa657BigIntTb4b4b4(Tff7b72thisTb4b4b4.Te6edf3bTb4b4b4[Tff7b72thisTb4b4b4.Te6edf3pTff7b72+Te6edf3iTb4b4b4]Tb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72thisTb4b4b4.Te6edf3pTff7b72+=T79c0ff8Tb4b4b4; Tff7b72return Te6edf3vTb4b4b4; Tb4b4b4}
Te6edf3_bytesTb4b4b4(Te6edf3nTb4b4b4)Tb4b4b4{ Tff7b72const Te6edf3vTff7b72=Tff7b72thisTb4b4b4.Te6edf3bTb4b4b4.Te6edf3sliceTb4b4b4(Tff7b72thisTb4b4b4.Te6edf3pTb4b4b4,Tff7b72thisTb4b4b4.Te6edf3pTff7b72+Te6edf3nTb4b4b4)Tb4b4b4; Tff7b72thisTb4b4b4.Te6edf3pTff7b72+=Te6edf3nTb4b4b4; Tff7b72return Te6edf3vTb4b4b4; Tb4b4b4}
Te6edf3_f32Tb4b4b4(Tb4b4b4)Tb4b4b4{ Tff7b72const Te6edf3dvTff7b72=Tff7b72new Tffa657DataViewTb4b4b4(Tff7b72thisTb4b4b4.Te6edf3bTb4b4b4.Te6edf3bufferTb4b4b4,Tff7b72thisTb4b4b4.Te6edf3bTb4b4b4.Te6edf3byteOffsetTff7b72+Tff7b72thisTb4b4b4.Te6edf3pTb4b4b4,T79c0ff4Tb4b4b4)Tb4b4b4; Tff7b72thisTb4b4b4.Te6edf3pTff7b72+=T79c0ff4Tb4b4b4; Tff7b72return Te6edf3dvTb4b4b4.Te6edf3getFloat32Tb4b4b4(T79c0ff0Tb4b4b4,Tff7b72falseTb4b4b4)Tb4b4b4; Tb4b4b4}
Te6edf3_f64Tb4b4b4(Tb4b4b4)Tb4b4b4{ Tff7b72const Te6edf3dvTff7b72=Tff7b72new Tffa657DataViewTb4b4b4(Tff7b72thisTb4b4b4.Te6edf3bTb4b4b4.Te6edf3bufferTb4b4b4,Tff7b72thisTb4b4b4.Te6edf3bTb4b4b4.Te6edf3byteOffsetTff7b72+Tff7b72thisTb4b4b4.Te6edf3pTb4b4b4,T79c0ff8Tb4b4b4)Tb4b4b4; Tff7b72thisTb4b4b4.Te6edf3pTff7b72+=T79c0ff8Tb4b4b4; Tff7b72return Te6edf3dvTb4b4b4.Te6edf3getFloat64Tb4b4b4(T79c0ff0Tb4b4b4,Tff7b72falseTb4b4b4)Tb4b4b4; Tb4b4b4}
Te6edf3_arrTb4b4b4(Te6edf3nTb4b4b4)Tb4b4b4{ Tff7b72const Te6edf3aTff7b72=Tff7b72new Tffa657ArrayTb4b4b4(Te6edf3nTb4b4b4)Tb4b4b4; Tff7b72forTb4b4b4(Tff7b72let Te6edf3iTff7b72=T79c0ff0Tb4b4b4;Te6edf3iTff7b72<Te6edf3nTb4b4b4;Tff7b72++Te6edf3iTb4b4b4) Te6edf3aTb4b4b4[Te6edf3iTb4b4b4]Tff7b72=Tff7b72thisTb4b4b4.Te6edf3nextTb4b4b4(Tb4b4b4)Tb4b4b4; Tff7b72return Te6edf3aTb4b4b4; Tb4b4b4}
Te6edf3_mapTb4b4b4(Te6edf3nTb4b4b4)Tb4b4b4{ Tff7b72const Te6edf3mTff7b72=Tff7b72new Tffa657MapTb4b4b4(Tb4b4b4)Tb4b4b4; Tff7b72forTb4b4b4(Tff7b72let Te6edf3iTff7b72=T79c0ff0Tb4b4b4;Te6edf3iTff7b72<Te6edf3nTb4b4b4;Tff7b72++Te6edf3iTb4b4b4)Tb4b4b4{ Tff7b72const Te6edf3kTff7b72=Tff7b72thisTb4b4b4.Te6edf3nextTb4b4b4(Tb4b4b4)Tb4b4b4; Te6edf3mTb4b4b4.Te6edf3setTb4b4b4(Te6edf3kTb4b4b4,Tff7b72thisTb4b4b4.Te6edf3nextTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72return Te6edf3mTb4b4b4; Tb4b4b4}
Te6edf3nextTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3tTff7b72=Tff7b72thisTb4b4b4.Te6edf3_r8Tb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3tTff7b72<=T79c0ff0x7fTb4b4b4) Tff7b72return Te6edf3tTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3tTff7b72>=T79c0ff0xe0Tb4b4b4) Tff7b72return Te6edf3tTff7b72-T79c0ff0x100Tb4b4b4;
Tff7b72if Tb4b4b4(Tb4b4b4(Te6edf3tTff7b72&T79c0ff0xe0Tb4b4b4)Tff7b72===T79c0ff0xa0Tb4b4b4) Tff7b72return Tff7b72thisTb4b4b4.Te6edf3decTb4b4b4.Te6edf3decodeTb4b4b4(Tff7b72thisTb4b4b4.Te6edf3_bytesTb4b4b4(Te6edf3tTff7b72&T79c0ff0x1fTb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tb4b4b4(Te6edf3tTff7b72&T79c0ff0xf0Tb4b4b4)Tff7b72===T79c0ff0x90Tb4b4b4) Tff7b72return Tff7b72thisTb4b4b4.Te6edf3_arrTb4b4b4(Te6edf3tTff7b72&T79c0ff0x0fTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tb4b4b4(Te6edf3tTff7b72&T79c0ff0xf0Tb4b4b4)Tff7b72===T79c0ff0x80Tb4b4b4) Tff7b72return Tff7b72thisTb4b4b4.Te6edf3_mapTb4b4b4(Te6edf3tTff7b72&T79c0ff0x0fTb4b4b4)Tb4b4b4;
Tff7b72switchTb4b4b4(Te6edf3tTb4b4b4)Tb4b4b4{
Tff7b72case T79c0ff0xc0Tff7b72: Tff7b72return Tff7b72nullTb4b4b4;
Tff7b72case T79c0ff0xc2Tff7b72: Tff7b72return Tff7b72falseTb4b4b4;
Tff7b72case T79c0ff0xc3Tff7b72: Tff7b72return Tff7b72trueTb4b4b4;
Tff7b72case T79c0ff0xc4Tff7b72: Tff7b72return Tff7b72thisTb4b4b4.Te6edf3_bytesTb4b4b4(Tff7b72thisTb4b4b4.Te6edf3_r8Tb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72case T79c0ff0xc5Tff7b72: Tff7b72return Tff7b72thisTb4b4b4.Te6edf3_bytesTb4b4b4(Tff7b72thisTb4b4b4.Te6edf3_r16Tb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72case T79c0ff0xc6Tff7b72: Tff7b72return Tff7b72thisTb4b4b4.Te6edf3_bytesTb4b4b4(Tff7b72thisTb4b4b4.Te6edf3_r32Tb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72case T79c0ff0xcaTff7b72: Tff7b72return Tff7b72thisTb4b4b4.Te6edf3_f32Tb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72case T79c0ff0xcbTff7b72: Tff7b72return Tff7b72thisTb4b4b4.Te6edf3_f64Tb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72case T79c0ff0xccTff7b72: Tff7b72return Tff7b72thisTb4b4b4.Te6edf3_r8Tb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72case T79c0ff0xcdTff7b72: Tff7b72return Tff7b72thisTb4b4b4.Te6edf3_r16Tb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72case T79c0ff0xceTff7b72: Tff7b72return Tff7b72thisTb4b4b4.Te6edf3_r32Tb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72case T79c0ff0xcfTff7b72: Tb4b4b4{ Tff7b72const Te6edf3vTff7b72=Tff7b72thisTb4b4b4.Te6edf3_r64uTb4b4b4(Tb4b4b4)Tb4b4b4; Tff7b72return Te6edf3vTff7b72<=Tffa657BigIntTb4b4b4(Tffa657NumberTb4b4b4.Te6edf3MAX_SAFE_INTEGERTb4b4b4) Tff7b72? Tffa657NumberTb4b4b4(Te6edf3vTb4b4b4) Tff7b72: Te6edf3vTb4b4b4; Tb4b4b4}
Tff7b72case T79c0ff0xd0Tff7b72: Tb4b4b4{ Tff7b72const Te6edf3vTff7b72=Tff7b72thisTb4b4b4.Te6edf3_r8Tb4b4b4(Tb4b4b4)Tb4b4b4; Tff7b72return Te6edf3vTff7b72<T79c0ff128 Tff7b72? Te6edf3v Tff7b72: Te6edf3vTff7b72-T79c0ff256Tb4b4b4; Tb4b4b4}
Tff7b72case T79c0ff0xd1Tff7b72: Tb4b4b4{ Tff7b72const Te6edf3vTff7b72=Tff7b72thisTb4b4b4.Te6edf3_r16Tb4b4b4(Tb4b4b4)Tb4b4b4; Tff7b72return Te6edf3vTff7b72<T79c0ff32768 Tff7b72? Te6edf3v Tff7b72: Te6edf3vTff7b72-T79c0ff65536Tb4b4b4; Tb4b4b4}
Tff7b72case T79c0ff0xd2Tff7b72: Tb4b4b4{ Tff7b72const Te6edf3vTff7b72=Tff7b72thisTb4b4b4.Te6edf3_r32Tb4b4b4(Tb4b4b4)Tb4b4b4; Tff7b72return Te6edf3vTff7b72<T79c0ff2147483648 Tff7b72? Te6edf3v Tff7b72: Te6edf3vTff7b72-T79c0ff4294967296Tb4b4b4; Tb4b4b4}
Tff7b72case T79c0ff0xd3Tff7b72: Tb4b4b4{ Tff7b72let Te6edf3vTff7b72=Tff7b72thisTb4b4b4.Te6edf3_r64uTb4b4b4(Tb4b4b4)Tb4b4b4; Tff7b72if Tb4b4b4(Te6edf3vTff7b72>=Tb4b4b4(T79c0ff1nTff7b72<<T79c0ff63nTb4b4b4)Tb4b4b4) Te6edf3vTff7b72-=Tb4b4b4(T79c0ff1nTff7b72<<T79c0ff64nTb4b4b4)Tb4b4b4; Tff7b72return Te6edf3vTff7b72>=Tffa657BigIntTb4b4b4(Tffa657NumberTb4b4b4.Te6edf3MIN_SAFE_INTEGERTb4b4b4)Tff7b72&&Te6edf3vTff7b72<=Tffa657BigIntTb4b4b4(Tffa657NumberTb4b4b4.Te6edf3MAX_SAFE_INTEGERTb4b4b4) Tff7b72? Tffa657NumberTb4b4b4(Te6edf3vTb4b4b4) Tff7b72: Te6edf3vTb4b4b4; Tb4b4b4}
Tff7b72case T79c0ff0xd9Tff7b72: Tff7b72return Tff7b72thisTb4b4b4.Te6edf3decTb4b4b4.Te6edf3decodeTb4b4b4(Tff7b72thisTb4b4b4.Te6edf3_bytesTb4b4b4(Tff7b72thisTb4b4b4.Te6edf3_r8Tb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72case T79c0ff0xdaTff7b72: Tff7b72return Tff7b72thisTb4b4b4.Te6edf3decTb4b4b4.Te6edf3decodeTb4b4b4(Tff7b72thisTb4b4b4.Te6edf3_bytesTb4b4b4(Tff7b72thisTb4b4b4.Te6edf3_r16Tb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72case T79c0ff0xdbTff7b72: Tff7b72return Tff7b72thisTb4b4b4.Te6edf3decTb4b4b4.Te6edf3decodeTb4b4b4(Tff7b72thisTb4b4b4.Te6edf3_bytesTb4b4b4(Tff7b72thisTb4b4b4.Te6edf3_r32Tb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72case T79c0ff0xdcTff7b72: Tff7b72return Tff7b72thisTb4b4b4.Te6edf3_arrTb4b4b4(Tff7b72thisTb4b4b4.Te6edf3_r16Tb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72case T79c0ff0xddTff7b72: Tff7b72return Tff7b72thisTb4b4b4.Te6edf3_arrTb4b4b4(Tff7b72thisTb4b4b4.Te6edf3_r32Tb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72case T79c0ff0xdeTff7b72: Tff7b72return Tff7b72thisTb4b4b4.Te6edf3_mapTb4b4b4(Tff7b72thisTb4b4b4.Te6edf3_r16Tb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72case T79c0ff0xdfTff7b72: Tff7b72return Tff7b72thisTb4b4b4.Te6edf3_mapTb4b4b4(Tff7b72thisTb4b4b4.Te6edf3_r32Tb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72throw Tff7b72new Tf85149ErrorTb4b4b4(Ta5d6ff'msgpack: unknown type 0x'Tff7b72+Te6edf3tTb4b4b4.Te6edf3toStringTb4b4b4(T79c0ff16Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}

T8b949e// ===== KISS framing =====
Tff7b72function Te6edf3kissEncodeTb4b4b4(Te6edf3cmdTb4b4b4, Te6edf3payloadTb4b4b4) Tb4b4b4{
Tff7b72let Te6edf3len Tff7b72= T79c0ff2Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72let Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< Te6edf3payloadTb4b4b4.Te6edf3lengthTb4b4b4; Tff7b72++Te6edf3iTb4b4b4) Te6edf3len Tff7b72+= Tb4b4b4(Te6edf3payloadTb4b4b4[Te6edf3iTb4b4b4] Tff7b72=== Te6edf3FEND Tff7b72|| Te6edf3payloadTb4b4b4[Te6edf3iTb4b4b4] Tff7b72=== Te6edf3FESCTb4b4b4) Tff7b72? T79c0ff2 Tff7b72: T79c0ff1Tb4b4b4;
Te6edf3len Tff7b72+= T79c0ff1Tb4b4b4;
Tff7b72const Te6edf3out Tff7b72= Tff7b72new Tffa657Uint8ArrayTb4b4b4(Te6edf3lenTb4b4b4)Tb4b4b4;
Tff7b72let Te6edf3o Tff7b72= T79c0ff0Tb4b4b4;
Te6edf3outTb4b4b4[Te6edf3oTff7b72++Tb4b4b4] Tff7b72= Te6edf3FENDTb4b4b4; Te6edf3outTb4b4b4[Te6edf3oTff7b72++Tb4b4b4] Tff7b72= Te6edf3cmdTb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72let Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< Te6edf3payloadTb4b4b4.Te6edf3lengthTb4b4b4; Tff7b72++Te6edf3iTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3b Tff7b72= Te6edf3payloadTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3b Tff7b72=== Te6edf3FENDTb4b4b4) Tb4b4b4{ Te6edf3outTb4b4b4[Te6edf3oTff7b72++Tb4b4b4] Tff7b72= Te6edf3FESCTb4b4b4; Te6edf3outTb4b4b4[Te6edf3oTff7b72++Tb4b4b4] Tff7b72= Te6edf3TFENDTb4b4b4; Tb4b4b4}
Tff7b72else Tff7b72if Tb4b4b4(Te6edf3b Tff7b72=== Te6edf3FESCTb4b4b4) Tb4b4b4{ Te6edf3outTb4b4b4[Te6edf3oTff7b72++Tb4b4b4] Tff7b72= Te6edf3FESCTb4b4b4; Te6edf3outTb4b4b4[Te6edf3oTff7b72++Tb4b4b4] Tff7b72= Te6edf3TFESCTb4b4b4; Tb4b4b4}
Tff7b72else Tb4b4b4{ Te6edf3outTb4b4b4[Te6edf3oTff7b72++Tb4b4b4] Tff7b72= Te6edf3bTb4b4b4; Tb4b4b4}
Tb4b4b4}
Te6edf3outTb4b4b4[Te6edf3oTff7b72++Tb4b4b4] Tff7b72= Te6edf3FENDTb4b4b4;
Tff7b72return Te6edf3outTb4b4b4;
Tb4b4b4}
Tff7b72class Te6edf3KissDecoder Tb4b4b4{
Tff7b72constructorTb4b4b4(Te6edf3onFrameTb4b4b4) Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3onFrame Tff7b72= Te6edf3onFrameTb4b4b4; Tff7b72thisTb4b4b4.Te6edf3state Tff7b72= Ta5d6ff'idle'Tb4b4b4; Tff7b72thisTb4b4b4.Te6edf3cmd Tff7b72= T79c0ff0Tb4b4b4; Tff7b72thisTb4b4b4.Te6edf3buf Tff7b72= Tb4b4b4[Tb4b4b4]Tb4b4b4; Tff7b72thisTb4b4b4.Te6edf3esc Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Te6edf3feedTb4b4b4(Te6edf3bytesTb4b4b4) Tb4b4b4{
Tff7b72for Tb4b4b4(Tff7b72let Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< Te6edf3bytesTb4b4b4.Te6edf3lengthTb4b4b4; Tff7b72++Te6edf3iTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3b Tff7b72= Te6edf3bytesTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3state Tff7b72=== Ta5d6ff'idle'Tb4b4b4) Tb4b4b4{ Tff7b72if Tb4b4b4(Te6edf3b Tff7b72=== Te6edf3FENDTb4b4b4) Tff7b72thisTb4b4b4.Te6edf3state Tff7b72= Ta5d6ff'cmd'Tb4b4b4; Tff7b72continueTb4b4b4; Tb4b4b4}
Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3state Tff7b72=== Ta5d6ff'cmd'Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3b Tff7b72=== Te6edf3FENDTb4b4b4) Tff7b72continueTb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3cmd Tff7b72= Te6edf3bTb4b4b4; Tff7b72thisTb4b4b4.Te6edf3buf Tff7b72= Tb4b4b4[Tb4b4b4]Tb4b4b4; Tff7b72thisTb4b4b4.Te6edf3esc Tff7b72= Tff7b72falseTb4b4b4; Tff7b72thisTb4b4b4.Te6edf3state Tff7b72= Ta5d6ff'data'Tb4b4b4;
Tff7b72continueTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3b Tff7b72=== Te6edf3FENDTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3bufTb4b4b4.Te6edf3length Tff7b72> T79c0ff0Tb4b4b4) Tff7b72thisTb4b4b4.Te6edf3onFrameTb4b4b4(Tff7b72thisTb4b4b4.Te6edf3cmdTb4b4b4, Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tff7b72thisTb4b4b4.Te6edf3bufTb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3state Tff7b72= Ta5d6ff'cmd'Tb4b4b4;
Tff7b72continueTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3escTb4b4b4) Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3bufTb4b4b4.Te6edf3pushTb4b4b4(Te6edf3b Tff7b72=== Te6edf3TFEND Tff7b72? Te6edf3FEND Tff7b72: Tb4b4b4(Te6edf3b Tff7b72=== Te6edf3TFESC Tff7b72? Te6edf3FESC Tff7b72: Te6edf3bTb4b4b4)Tb4b4b4)Tb4b4b4; Tff7b72thisTb4b4b4.Te6edf3esc Tff7b72= Tff7b72falseTb4b4b4; Tff7b72continueTb4b4b4; Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3b Tff7b72=== Te6edf3FESCTb4b4b4) Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3esc Tff7b72= Tff7b72trueTb4b4b4; Tff7b72continueTb4b4b4; Tb4b4b4}
Tff7b72thisTb4b4b4.Te6edf3bufTb4b4b4.Te6edf3pushTb4b4b4(Te6edf3bTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

T8b949e// ===== Transports =====
Tff7b72class Te6edf3SerialTransport Tb4b4b4{
Tff7b72constructorTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3portTff7b72=Tff7b72nullTb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3readerTff7b72=Tff7b72nullTb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3writerTff7b72=Tff7b72nullTb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3onBytesTff7b72=Tb4b4b4(Tb4b4b4)Tb4b4b4=>Tb4b4b4{Tb4b4b4}Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3onStatusTff7b72=Tb4b4b4(Tb4b4b4)Tb4b4b4=>Tb4b4b4{Tb4b4b4}Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3_abortTff7b72=Tff7b72falseTb4b4b4;
T8b949e// ────────────────────────────────────────────────────────────────────
T8b949e// TEMPORARY WORKAROUND for a Chrome Web Serial quirk:
T8b949e// After a physical USB disconnect/reconnect cycle (e.g. device reset
T8b949e// on a CDC-USB board), Chrome leaves the SerialPort JS object in a
T8b949e// half-bound state where port.open() throws "Failed to open serial
T8b949e// port." until the user re-prompts via requestPort(). Permission to
T8b949e// access the device persists, but the JS object's internal binding
T8b949e// is wedged.
T8b949e//
T8b949e// To recover without forcing the user to re-pick, we listen for the
T8b949e// navigator.serial 'disconnect' / 'connect' events: the 'connect' on
T8b949e// our port signals that Chrome has finished rebinding to the
T8b949e// re-enumerated device, at which point open() succeeds cleanly.
T8b949e// reconnect() blocks on this signal before attempting open().
T8b949e//
T8b949e// Remove once Chrome bug is fixed (track: open issues against
T8b949e// chromium/web-serial covering "SerialPort.open() fails after USB
T8b949e// disconnect/reconnect"). Until then the bail-after-5-failures path
T8b949e// in startReconnect() remains as a safety net for cases where no
T8b949e// 'connect' event ever fires (e.g. permission revoked, device gone
T8b949e// for good).
T8b949e// ────────────────────────────────────────────────────────────────────
Tff7b72thisTb4b4b4.Te6edf3_physicallyDisconnected Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3_physicalReconnectWaiters Tff7b72= Tb4b4b4[Tb4b4b4]Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3_navConnectHandler Tff7b72= Tff7b72nullTb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3_navDisconnectHandler Tff7b72= Tff7b72nullTb4b4b4;
Tb4b4b4}
Tff7b72static Te6edf3availableTb4b4b4(Tb4b4b4)Tb4b4b4{ Tff7b72return Tff7b72!Tff7b72!Te6edf3navigatorTb4b4b4.Te6edf3serialTb4b4b4; Tb4b4b4}
Te6edf3_descTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Tff7b72thisTb4b4b4.Te6edf3portTb4b4b4) Tff7b72return Ta5d6ff'serial port'Tb4b4b4;
Tff7b72const Te6edf3info Tff7b72= Tff7b72thisTb4b4b4.Te6edf3portTb4b4b4.Te6edf3getInfoTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72return Te6edf3infoTb4b4b4.Te6edf3usbVendorId
Tff7b72? Ta5d6ff`Ta5d6ffUSB Tffd700${Te6edf3infoTb4b4b4.Te6edf3usbVendorIdTb4b4b4.Te6edf3toStringTb4b4b4(T79c0ff16Tb4b4b4)Tb4b4b4.Te6edf3padStartTb4b4b4(T79c0ff4Tb4b4b4,Ta5d6ff'0'Tb4b4b4)Tffd700}Ta5d6ff:Tffd700${Tb4b4b4(Te6edf3infoTb4b4b4.Te6edf3usbProductIdTff7b72||T79c0ff0Tb4b4b4)Tb4b4b4.Te6edf3toStringTb4b4b4(T79c0ff16Tb4b4b4)Tb4b4b4.Te6edf3padStartTb4b4b4(T79c0ff4Tb4b4b4,Ta5d6ff'0'Tb4b4b4)Tffd700}Ta5d6ff`
Tff7b72: Ta5d6ff'serial port'Tb4b4b4;
Tb4b4b4}
T8b949e// Match a port from a connect/disconnect event against our handle. Tries
T8b949e// instance equality first (the spec-blessed path), then falls back to
T8b949e// VID/PID equality because in practice Chrome sometimes hands out a *new*
T8b949e// SerialPort JS object for the same physical device after re-enumeration —
T8b949e// making `ev.target === this.port` unreliable for our purpose.
Te6edf3_portsMatchTb4b4b4(Te6edf3otherPortTb4b4b4)Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Tff7b72thisTb4b4b4.Te6edf3port Tff7b72|| Tff7b72!Te6edf3otherPortTb4b4b4) Tff7b72return Tff7b72falseTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3otherPort Tff7b72=== Tff7b72thisTb4b4b4.Te6edf3portTb4b4b4) Tff7b72return Tff7b72trueTb4b4b4;
Tff7b72try Tb4b4b4{
Tff7b72const Te6edf3a Tff7b72= Tff7b72thisTb4b4b4.Te6edf3portTb4b4b4.Te6edf3getInfoTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3b Tff7b72= Te6edf3otherPortTb4b4b4.Te6edf3getInfoTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3aTb4b4b4.Te6edf3usbVendorId Tff7b72== Tff7b72null Tff7b72|| Te6edf3bTb4b4b4.Te6edf3usbVendorId Tff7b72== Tff7b72nullTb4b4b4) Tff7b72return Tff7b72falseTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3aTb4b4b4.Te6edf3usbVendorId Tff7b72!== Te6edf3bTb4b4b4.Te6edf3usbVendorIdTb4b4b4) Tff7b72return Tff7b72falseTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3aTb4b4b4.Te6edf3usbProductId Tff7b72!== Te6edf3bTb4b4b4.Te6edf3usbProductIdTb4b4b4) Tff7b72return Tff7b72falseTb4b4b4;
T8b949e// usbSerialNumber is the most specific discriminator when available.
T8b949e// If only one side has it, accept VID+PID alone — better to attempt
T8b949e// open and let it fail than to miss a legitimate reconnect.
Tff7b72if Tb4b4b4(Te6edf3aTb4b4b4.Te6edf3usbSerialNumber Tff7b72&& Te6edf3bTb4b4b4.Te6edf3usbSerialNumberTb4b4b4) Tb4b4b4{
Tff7b72return Te6edf3aTb4b4b4.Te6edf3usbSerialNumber Tff7b72=== Te6edf3bTb4b4b4.Te6edf3usbSerialNumberTb4b4b4;
Tb4b4b4}
Tff7b72return Tff7b72trueTb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{ Tff7b72return Tff7b72falseTb4b4b4; Tb4b4b4}
Tb4b4b4}
T8b949e// See workaround note in the constructor. Installed on first connect, removed
T8b949e// on disconnect. Filters events by port identity (with VID/PID fallback) so
T8b949e// multiple SerialTransport instances (or other listeners) don't cross-talk.
Te6edf3_installNavSerialListenersTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3navigatorTb4b4b4.Te6edf3serial Tff7b72|| Tff7b72thisTb4b4b4.Te6edf3_navConnectHandlerTb4b4b4) Tff7b72returnTb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3_navDisconnectHandler Tff7b72= Tb4b4b4(Te6edf3evTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3match Tff7b72= Tff7b72thisTb4b4b4.Te6edf3_portsMatchTb4b4b4(Te6edf3evTb4b4b4.Te6edf3targetTb4b4b4)Tb4b4b4;
Te6edf3consoleTb4b4b4.Te6edf3debugTb4b4b4(Ta5d6ff'[serial] disconnect event, match='Tb4b4b4, Te6edf3matchTb4b4b4, Ta5d6ff'target='Tb4b4b4, Te6edf3evTb4b4b4.Te6edf3targetTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3matchTb4b4b4) Tff7b72thisTb4b4b4.Te6edf3_physicallyDisconnected Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4}Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3_navConnectHandler Tff7b72= Tb4b4b4(Te6edf3evTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3match Tff7b72= Tff7b72thisTb4b4b4.Te6edf3_portsMatchTb4b4b4(Te6edf3evTb4b4b4.Te6edf3targetTb4b4b4)Tb4b4b4;
Te6edf3consoleTb4b4b4.Te6edf3debugTb4b4b4(Ta5d6ff'[serial] connect event, match='Tb4b4b4, Te6edf3matchTb4b4b4, Ta5d6ff'target='Tb4b4b4, Te6edf3evTb4b4b4.Te6edf3targetTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3matchTb4b4b4) Tff7b72returnTb4b4b4;
T8b949e// Chrome may have handed us a fresh SerialPort instance for the
T8b949e// re-enumerated device. Adopt it so subsequent open() / read /
T8b949e// write all happen against the live handle, not the stale one.
Tff7b72if Tb4b4b4(Te6edf3evTb4b4b4.Te6edf3target Tff7b72!== Tff7b72thisTb4b4b4.Te6edf3portTb4b4b4) Tb4b4b4{
Te6edf3consoleTb4b4b4.Te6edf3debugTb4b4b4(Ta5d6ff'[serial] adopting new port instance from connect event'Tb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3port Tff7b72= Te6edf3evTb4b4b4.Te6edf3targetTb4b4b4;
Tb4b4b4}
Tff7b72thisTb4b4b4.Te6edf3_physicallyDisconnected Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72const Te6edf3ws Tff7b72= Tff7b72thisTb4b4b4.Te6edf3_physicalReconnectWaitersTb4b4b4.Te6edf3spliceTb4b4b4(T79c0ff0Tb4b4b4)Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3r Tff7b72of Te6edf3wsTb4b4b4) Tb4b4b4{ Tff7b72try Tb4b4b4{ Te6edf3rTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4} Tb4b4b4}
Tb4b4b4}Tb4b4b4;
Te6edf3navigatorTb4b4b4.Te6edf3serialTb4b4b4.Te6edf3addEventListenerTb4b4b4(Ta5d6ff'disconnect'Tb4b4b4, Tff7b72thisTb4b4b4.Te6edf3_navDisconnectHandlerTb4b4b4)Tb4b4b4;
Te6edf3navigatorTb4b4b4.Te6edf3serialTb4b4b4.Te6edf3addEventListenerTb4b4b4(Ta5d6ff'connect'Tb4b4b4, Tff7b72thisTb4b4b4.Te6edf3_navConnectHandlerTb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3_removeNavSerialListenersTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3navigatorTb4b4b4.Te6edf3serialTb4b4b4) Tff7b72returnTb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3_navDisconnectHandlerTb4b4b4) Tb4b4b4{
Te6edf3navigatorTb4b4b4.Te6edf3serialTb4b4b4.Te6edf3removeEventListenerTb4b4b4(Ta5d6ff'disconnect'Tb4b4b4, Tff7b72thisTb4b4b4.Te6edf3_navDisconnectHandlerTb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3_navDisconnectHandler Tff7b72= Tff7b72nullTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3_navConnectHandlerTb4b4b4) Tb4b4b4{
Te6edf3navigatorTb4b4b4.Te6edf3serialTb4b4b4.Te6edf3removeEventListenerTb4b4b4(Ta5d6ff'connect'Tb4b4b4, Tff7b72thisTb4b4b4.Te6edf3_navConnectHandlerTb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3_navConnectHandler Tff7b72= Tff7b72nullTb4b4b4;
Tb4b4b4}
T8b949e// Resolve any pending waiters so they don't leak.
Tff7b72const Te6edf3ws Tff7b72= Tff7b72thisTb4b4b4.Te6edf3_physicalReconnectWaitersTb4b4b4.Te6edf3spliceTb4b4b4(T79c0ff0Tb4b4b4)Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3r Tff7b72of Te6edf3wsTb4b4b4) Tb4b4b4{ Tff7b72try Tb4b4b4{ Te6edf3rTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4} Tb4b4b4}
Tb4b4b4}
Te6edf3_waitForPhysicalReconnectTb4b4b4(Te6edf3timeoutMsTb4b4b4)Tb4b4b4{
Tff7b72return Tff7b72new Tffa657PromiseTb4b4b4(Tb4b4b4(Te6edf3resolveTb4b4b4, Te6edf3rejectTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3wrap Tff7b72= Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{ Te6edf3clearTimeoutTb4b4b4(Te6edf3timerTb4b4b4)Tb4b4b4; Te6edf3resolveTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4}Tb4b4b4;
Tff7b72const Te6edf3timer Tff7b72= Te6edf3setTimeoutTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3idx Tff7b72= Tff7b72thisTb4b4b4.Te6edf3_physicalReconnectWaitersTb4b4b4.Te6edf3indexOfTb4b4b4(Te6edf3wrapTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3idx Tff7b72>= T79c0ff0Tb4b4b4) Tff7b72thisTb4b4b4.Te6edf3_physicalReconnectWaitersTb4b4b4.Te6edf3spliceTb4b4b4(Te6edf3idxTb4b4b4, T79c0ff1Tb4b4b4)Tb4b4b4;
Te6edf3rejectTb4b4b4(Tff7b72new Tf85149ErrorTb4b4b4(Ta5d6ff'timed out waiting for device to reappear'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4, Te6edf3timeoutMsTb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3_physicalReconnectWaitersTb4b4b4.Te6edf3pushTb4b4b4(Te6edf3wrapTb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72async Te6edf3connectTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3onStatusTb4b4b4(Tb4b4b4{Te6edf3stateTff7b72:Ta5d6ff'connecting'Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72try Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3port Tff7b72= Tff7b72await Te6edf3navigatorTb4b4b4.Te6edf3serialTb4b4b4.Te6edf3requestPortTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3_installNavSerialListenersTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72await Tff7b72thisTb4b4b4.Te6edf3_openTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3onStatusTb4b4b4(Tb4b4b4{Te6edf3stateTff7b72:Ta5d6ff'error'Tb4b4b4, Te6edf3infoTff7b72: Te6edf3eTb4b4b4.Te6edf3message Tff7b72|| Tffa657StringTb4b4b4(Te6edf3eTb4b4b4)Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72throw Te6edf3eTb4b4b4;
Tb4b4b4}
Tb4b4b4}
T8b949e// Reconnect using the existing port handle — no user gesture needed because
T8b949e// permission was granted during the initial connect. If the device went
T8b949e// through a physical disconnect/reconnect, wait for the navigator.serial
T8b949e// 'connect' event before opening (see workaround note in the constructor).
Tff7b72async Te6edf3reconnectTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Tff7b72thisTb4b4b4.Te6edf3portTb4b4b4) Tff7b72throw Tff7b72new Tf85149ErrorTb4b4b4(Ta5d6ff'no port to reconnect'Tb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3onStatusTb4b4b4(Tb4b4b4{Te6edf3stateTff7b72:Ta5d6ff'connecting'Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3consoleTb4b4b4.Te6edf3debugTb4b4b4(Ta5d6ff'[serial] reconnect: _physicallyDisconnected='Tb4b4b4, Tff7b72thisTb4b4b4.Te6edf3_physicallyDisconnectedTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3_physicallyDisconnectedTb4b4b4) Tb4b4b4{
Tff7b72try Tb4b4b4{ Tff7b72await Tff7b72thisTb4b4b4.Te6edf3_waitForPhysicalReconnectTb4b4b4(T79c0ff3000Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Te6edf3consoleTb4b4b4.Te6edf3debugTb4b4b4(Ta5d6ff'[serial] wait for physical reconnect timed out'Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4}
Tff7b72await Tff7b72thisTb4b4b4.Te6edf3_openTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72async Te6edf3_openTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72await Tff7b72thisTb4b4b4.Te6edf3portTb4b4b4.Te6edf3openTb4b4b4(Tb4b4b4{ Te6edf3baudRateTff7b72: T79c0ff115200 Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3writer Tff7b72= Tff7b72thisTb4b4b4.Te6edf3portTb4b4b4.Te6edf3writableTb4b4b4.Te6edf3getWriterTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3reader Tff7b72= Tff7b72thisTb4b4b4.Te6edf3portTb4b4b4.Te6edf3readableTb4b4b4.Te6edf3getReaderTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3_abort Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3onStatusTb4b4b4(Tb4b4b4{Te6edf3stateTff7b72:Ta5d6ff'connected'Tb4b4b4, Te6edf3infoTff7b72: Tff7b72thisTb4b4b4.Te6edf3_descTb4b4b4(Tb4b4b4)Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3_readLoopTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72async Te6edf3_releaseStreamsTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72try Tb4b4b4{ Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3readerTb4b4b4) Tb4b4b4{ Tff7b72try Tb4b4b4{ Tff7b72await Tff7b72thisTb4b4b4.Te6edf3readerTb4b4b4.Te6edf3cancelTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4} Tff7b72try Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3readerTb4b4b4.Te6edf3releaseLockTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4} Tb4b4b4} Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4}
Tff7b72try Tb4b4b4{ Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3writerTb4b4b4) Tb4b4b4{ Tff7b72try Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3writerTb4b4b4.Te6edf3releaseLockTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4} Tb4b4b4} Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4}
Tff7b72try Tb4b4b4{ Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3portTb4b4b4) Tff7b72await Tff7b72thisTb4b4b4.Te6edf3portTb4b4b4.Te6edf3closeTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4}
Tff7b72thisTb4b4b4.Te6edf3reader Tff7b72= Tff7b72thisTb4b4b4.Te6edf3writer Tff7b72= Tff7b72nullTb4b4b4;
Tb4b4b4}
Tff7b72async Te6edf3_readLoopTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72try Tb4b4b4{
Tff7b72while Tb4b4b4(Tff7b72!Tff7b72thisTb4b4b4.Te6edf3_abortTb4b4b4) Tb4b4b4{
Tff7b72const Tb4b4b4{ Te6edf3valueTb4b4b4, Te6edf3done Tb4b4b4} Tff7b72= Tff7b72await Tff7b72thisTb4b4b4.Te6edf3readerTb4b4b4.Te6edf3readTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3doneTb4b4b4) Tff7b72breakTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3value Tff7b72&& Te6edf3valueTb4b4b4.Te6edf3lengthTb4b4b4) Tff7b72thisTb4b4b4.Te6edf3onBytesTb4b4b4(Te6edf3valueTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{
T8b949e// Lost-device or cancelled reader — fall through to teardown.
Tb4b4b4}
Tff7b72await Tff7b72thisTb4b4b4.Te6edf3_releaseStreamsTb4b4b4(Tb4b4b4)Tb4b4b4;
T8b949e// Keep this.port so reconnect() can re-open it without re-prompting.
Tff7b72thisTb4b4b4.Te6edf3onStatusTb4b4b4(Tb4b4b4{Te6edf3stateTff7b72:Ta5d6ff'closed'Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72async Te6edf3sendTb4b4b4(Te6edf3bytesTb4b4b4)Tb4b4b4{ Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3writerTb4b4b4) Tff7b72await Tff7b72thisTb4b4b4.Te6edf3writerTb4b4b4.Te6edf3writeTb4b4b4(Te6edf3bytesTb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72async Te6edf3disconnectTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3_abort Tff7b72= Tff7b72trueTb4b4b4;
Tff7b72await Tff7b72thisTb4b4b4.Te6edf3_releaseStreamsTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3port Tff7b72= Tff7b72nullTb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3_removeNavSerialListenersTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3onStatusTb4b4b4(Tb4b4b4{Te6edf3stateTff7b72:Ta5d6ff'idle'Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}
T8b949e// Soft-close that preserves the port handle so reconnect() can reopen it.
T8b949e// Used when we know the device is about to disconnect (e.g. after a reboot
T8b949e// command) — on UART-to-USB bridges the underlying serial connection may not
T8b949e// drop on its own, so we have to release it explicitly to trigger 'closed'.
T8b949e// We do NOT fire onStatus('closed') ourselves; cancelling the reader makes
T8b949e// _readLoop exit, and it fires 'closed' on its way out. Firing here too would
T8b949e// double-fire and spawn two parallel reconnect attempts.
Tff7b72async Te6edf3forceCloseTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3_abort Tff7b72= Tff7b72trueTb4b4b4;
Tff7b72await Tff7b72thisTb4b4b4.Te6edf3_releaseStreamsTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72const Te6edf3NUS_SERVICE Tff7b72= Ta5d6ff'6e400001-b5a3-f393-e0a9-e50e24dcca9e'Tb4b4b4;
Tff7b72const Te6edf3NUS_RX_CHAR Tff7b72= Ta5d6ff'6e400002-b5a3-f393-e0a9-e50e24dcca9e'Tb4b4b4;
Tff7b72const Te6edf3NUS_TX_CHAR Tff7b72= Ta5d6ff'6e400003-b5a3-f393-e0a9-e50e24dcca9e'Tb4b4b4;
Tff7b72class Te6edf3BLETransport Tb4b4b4{
Tff7b72constructorTb4b4b4(Tb4b4b4)Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3deviceTff7b72=Tff7b72nullTb4b4b4; Tff7b72thisTb4b4b4.Te6edf3rxTff7b72=Tff7b72nullTb4b4b4; Tff7b72thisTb4b4b4.Te6edf3txTff7b72=Tff7b72nullTb4b4b4; Tff7b72thisTb4b4b4.Te6edf3onBytesTff7b72=Tb4b4b4(Tb4b4b4)Tb4b4b4=>Tb4b4b4{Tb4b4b4}Tb4b4b4; Tff7b72thisTb4b4b4.Te6edf3onStatusTff7b72=Tb4b4b4(Tb4b4b4)Tb4b4b4=>Tb4b4b4{Tb4b4b4}Tb4b4b4; Tff7b72thisTb4b4b4.Te6edf3_writeNoRespTff7b72=Tff7b72trueTb4b4b4; Tff7b72thisTb4b4b4.Te6edf3_gattHandlerTff7b72=Tff7b72nullTb4b4b4; Tff7b72thisTb4b4b4.Te6edf3_notifyHandlerTff7b72=Tff7b72nullTb4b4b4; Tb4b4b4}
Tff7b72static Te6edf3availableTb4b4b4(Tb4b4b4)Tb4b4b4{ Tff7b72return Tff7b72!Tff7b72!Te6edf3navigatorTb4b4b4.Te6edf3bluetoothTb4b4b4; Tb4b4b4}
Tff7b72async Te6edf3connectTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3onStatusTb4b4b4(Tb4b4b4{Te6edf3stateTff7b72:Ta5d6ff'connecting'Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72try Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3device Tff7b72= Tff7b72await Te6edf3navigatorTb4b4b4.Te6edf3bluetoothTb4b4b4.Te6edf3requestDeviceTb4b4b4(Tb4b4b4{ Te6edf3filtersTff7b72: Tb4b4b4[Tb4b4b4{ Te6edf3servicesTff7b72: Tb4b4b4[Te6edf3NUS_SERVICETb4b4b4] Tb4b4b4}Tb4b4b4] Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3_gattHandler Tff7b72= Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tff7b72thisTb4b4b4.Te6edf3onStatusTb4b4b4(Tb4b4b4{Te6edf3stateTff7b72:Ta5d6ff'closed'Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3deviceTb4b4b4.Te6edf3addEventListenerTb4b4b4(Ta5d6ff'gattserverdisconnected'Tb4b4b4, Tff7b72thisTb4b4b4.Te6edf3_gattHandlerTb4b4b4)Tb4b4b4;
Tff7b72await Tff7b72thisTb4b4b4.Te6edf3_attachTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3onStatusTb4b4b4(Tb4b4b4{Te6edf3stateTff7b72:Ta5d6ff'error'Tb4b4b4, Te6edf3infoTff7b72: Te6edf3eTb4b4b4.Te6edf3message Tff7b72|| Tffa657StringTb4b4b4(Te6edf3eTb4b4b4)Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72throw Te6edf3eTb4b4b4;
Tb4b4b4}
Tb4b4b4}
T8b949e// Reconnect using the same device handle. No user gesture required.
Tff7b72async Te6edf3reconnectTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Tff7b72thisTb4b4b4.Te6edf3deviceTb4b4b4) Tff7b72throw Tff7b72new Tf85149ErrorTb4b4b4(Ta5d6ff'no device to reconnect'Tb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3onStatusTb4b4b4(Tb4b4b4{Te6edf3stateTff7b72:Ta5d6ff'connecting'Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72await Tff7b72thisTb4b4b4.Te6edf3_attachTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72async Te6edf3_attachTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3server Tff7b72= Tff7b72await Tff7b72thisTb4b4b4.Te6edf3deviceTb4b4b4.Te6edf3gattTb4b4b4.Te6edf3connectTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3svc Tff7b72= Tff7b72await Te6edf3serverTb4b4b4.Te6edf3getPrimaryServiceTb4b4b4(Te6edf3NUS_SERVICETb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3rx Tff7b72= Tff7b72await Te6edf3svcTb4b4b4.Te6edf3getCharacteristicTb4b4b4(Te6edf3NUS_RX_CHARTb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3tx Tff7b72= Tff7b72await Te6edf3svcTb4b4b4.Te6edf3getCharacteristicTb4b4b4(Te6edf3NUS_TX_CHARTb4b4b4)Tb4b4b4;
Tff7b72await Tff7b72thisTb4b4b4.Te6edf3txTb4b4b4.Te6edf3startNotificationsTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3_notifyHandler Tff7b72= Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3v Tff7b72= Te6edf3eTb4b4b4.Te6edf3targetTb4b4b4.Te6edf3valueTb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3onBytesTb4b4b4(Tff7b72new Tffa657Uint8ArrayTb4b4b4(Te6edf3vTb4b4b4.Te6edf3bufferTb4b4b4, Te6edf3vTb4b4b4.Te6edf3byteOffsetTb4b4b4, Te6edf3vTb4b4b4.Te6edf3byteLengthTb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3txTb4b4b4.Te6edf3addEventListenerTb4b4b4(Ta5d6ff'characteristicvaluechanged'Tb4b4b4, Tff7b72thisTb4b4b4.Te6edf3_notifyHandlerTb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3onStatusTb4b4b4(Tb4b4b4{Te6edf3stateTff7b72:Ta5d6ff'connected'Tb4b4b4, Te6edf3infoTff7b72: Tff7b72thisTb4b4b4.Te6edf3deviceTb4b4b4.Te6edf3name Tff7b72|| Ta5d6ff'BLE device'Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72async Te6edf3sendTb4b4b4(Te6edf3bytesTb4b4b4)Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Tff7b72thisTb4b4b4.Te6edf3rxTb4b4b4) Tff7b72returnTb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72let Te6edf3off Tff7b72= T79c0ff0Tb4b4b4; Te6edf3off Tff7b72< Te6edf3bytesTb4b4b4.Te6edf3lengthTb4b4b4; Te6edf3off Tff7b72+= T79c0ff240Tb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3chunk Tff7b72= Te6edf3bytesTb4b4b4.Te6edf3sliceTb4b4b4(Te6edf3offTb4b4b4, Tffa657MathTb4b4b4.Te6edf3minTb4b4b4(Te6edf3offTff7b72+T79c0ff240Tb4b4b4, Te6edf3bytesTb4b4b4.Te6edf3lengthTb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72try Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3_writeNoRespTb4b4b4) Tff7b72await Tff7b72thisTb4b4b4.Te6edf3rxTb4b4b4.Te6edf3writeValueWithoutResponseTb4b4b4(Te6edf3chunkTb4b4b4)Tb4b4b4;
Tff7b72else Tff7b72await Tff7b72thisTb4b4b4.Te6edf3rxTb4b4b4.Te6edf3writeValueTb4b4b4(Te6edf3chunkTb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3_writeNoRespTb4b4b4) Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3_writeNoResp Tff7b72= Tff7b72falseTb4b4b4; Tff7b72await Tff7b72thisTb4b4b4.Te6edf3rxTb4b4b4.Te6edf3writeValueTb4b4b4(Te6edf3chunkTb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72else Tff7b72throw Te6edf3eTb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72async Te6edf3disconnectTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72try Tb4b4b4{ Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3device Tff7b72&& Tff7b72thisTb4b4b4.Te6edf3_gattHandlerTb4b4b4) Tff7b72thisTb4b4b4.Te6edf3deviceTb4b4b4.Te6edf3removeEventListenerTb4b4b4(Ta5d6ff'gattserverdisconnected'Tb4b4b4, Tff7b72thisTb4b4b4.Te6edf3_gattHandlerTb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4}
Tff7b72try Tb4b4b4{ Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3device Tff7b72&& Tff7b72thisTb4b4b4.Te6edf3deviceTb4b4b4.Te6edf3gattTb4b4b4.Te6edf3connectedTb4b4b4) Tff7b72thisTb4b4b4.Te6edf3deviceTb4b4b4.Te6edf3gattTb4b4b4.Te6edf3disconnectTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4}
Tff7b72thisTb4b4b4.Te6edf3device Tff7b72= Tff7b72thisTb4b4b4.Te6edf3rx Tff7b72= Tff7b72thisTb4b4b4.Te6edf3tx Tff7b72= Tff7b72nullTb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3_gattHandler Tff7b72= Tff7b72thisTb4b4b4.Te6edf3_notifyHandler Tff7b72= Tff7b72nullTb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3onStatusTb4b4b4(Tb4b4b4{Te6edf3stateTff7b72:Ta5d6ff'idle'Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}
T8b949e// See SerialTransport.forceClose — drops the GATT link so we get a clean
T8b949e// disconnect/reconnect cycle. The gattserverdisconnected handler installed in
T8b949e// connect() will fire 'closed'. We do NOT fire it again here to avoid
T8b949e// double-triggering startReconnect.
Tff7b72async Te6edf3forceCloseTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72try Tb4b4b4{ Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3device Tff7b72&& Tff7b72thisTb4b4b4.Te6edf3deviceTb4b4b4.Te6edf3gattTb4b4b4.Te6edf3connectedTb4b4b4) Tff7b72thisTb4b4b4.Te6edf3deviceTb4b4b4.Te6edf3gattTb4b4b4.Te6edf3disconnectTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4}
Tff7b72thisTb4b4b4.Te6edf3rx Tff7b72= Tff7b72thisTb4b4b4.Te6edf3tx Tff7b72= Tff7b72nullTb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72class Te6edf3WebSocketTransport Tb4b4b4{
Tff7b72constructorTb4b4b4(Tb4b4b4)Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3wsTff7b72=Tff7b72nullTb4b4b4; Tff7b72thisTb4b4b4.Te6edf3urlTff7b72=Tff7b72nullTb4b4b4; Tff7b72thisTb4b4b4.Te6edf3onBytesTff7b72=Tb4b4b4(Tb4b4b4)Tb4b4b4=>Tb4b4b4{Tb4b4b4}Tb4b4b4; Tff7b72thisTb4b4b4.Te6edf3onStatusTff7b72=Tb4b4b4(Tb4b4b4)Tb4b4b4=>Tb4b4b4{Tb4b4b4}Tb4b4b4; Tff7b72thisTb4b4b4.Te6edf3_userClosingTff7b72=Tff7b72falseTb4b4b4; Tb4b4b4}
Tff7b72static Te6edf3availableTb4b4b4(Tb4b4b4)Tb4b4b4{ Tff7b72return Tff7b72trueTb4b4b4; Tb4b4b4}
Tff7b72async Te6edf3connectTb4b4b4(Te6edf3urlTb4b4b4)Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3url Tff7b72= Te6edf3urlTb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3onStatusTb4b4b4(Tb4b4b4{Te6edf3stateTff7b72:Ta5d6ff'connecting'Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72return Tff7b72new Tffa657PromiseTb4b4b4(Tb4b4b4(Te6edf3resolveTb4b4b4, Te6edf3rejectTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72try Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3ws Tff7b72= Tff7b72new Te6edf3WebSocketTb4b4b4(Te6edf3urlTb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3wsTb4b4b4.Te6edf3binaryType Tff7b72= Ta5d6ff'arraybuffer'Tb4b4b4;
Tff7b72let Te6edf3opened Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3wsTb4b4b4.Te6edf3onopen Tff7b72= Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{ Te6edf3opened Tff7b72= Tff7b72trueTb4b4b4; Tff7b72thisTb4b4b4.Te6edf3onStatusTb4b4b4(Tb4b4b4{Te6edf3stateTff7b72:Ta5d6ff'connected'Tb4b4b4, Te6edf3infoTff7b72: Te6edf3urlTb4b4b4}Tb4b4b4)Tb4b4b4; Te6edf3resolveTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4}Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3wsTb4b4b4.Te6edf3onmessage Tff7b72= Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3eTb4b4b4.Te6edf3data Tff7b72instanceof Tffa657ArrayBufferTb4b4b4) Tff7b72thisTb4b4b4.Te6edf3onBytesTb4b4b4(Tff7b72new Tffa657Uint8ArrayTb4b4b4(Te6edf3eTb4b4b4.Te6edf3dataTb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72else Tff7b72if Tb4b4b4(Tff7b72typeof Te6edf3eTb4b4b4.Te6edf3data Tff7b72=== Ta5d6ff'string'Tb4b4b4) Tff7b72thisTb4b4b4.Te6edf3onBytesTb4b4b4(Tff7b72new Te6edf3TextEncoderTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3encodeTb4b4b4(Te6edf3eTb4b4b4.Te6edf3dataTb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3wsTb4b4b4.Te6edf3onerror Tff7b72= Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{ Tff7b72if Tb4b4b4(Tff7b72!Te6edf3openedTb4b4b4) Te6edf3rejectTb4b4b4(Tff7b72new Tf85149ErrorTb4b4b4(Ta5d6ff'connect failed'Tb4b4b4)Tb4b4b4)Tb4b4b4; Tb4b4b4}Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3wsTb4b4b4.Te6edf3onclose Tff7b72= Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tff7b72thisTb4b4b4.Te6edf3onStatusTb4b4b4(Tb4b4b4{Te6edf3stateTff7b72: Tff7b72thisTb4b4b4.Te6edf3_userClosing Tff7b72? Ta5d6ff'idle' Tff7b72: Ta5d6ff'closed'Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3onStatusTb4b4b4(Tb4b4b4{Te6edf3stateTff7b72:Ta5d6ff'error'Tb4b4b4, Te6edf3infoTff7b72: Te6edf3eTb4b4b4.Te6edf3messageTb4b4b4}Tb4b4b4)Tb4b4b4; Te6edf3rejectTb4b4b4(Te6edf3eTb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}
T8b949e// Reconnect using the saved URL. Server-side socket from before the reboot
T8b949e// is gone, so we open a brand-new WebSocket.
Tff7b72async Te6edf3reconnectTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Tff7b72thisTb4b4b4.Te6edf3urlTb4b4b4) Tff7b72throw Tff7b72new Tf85149ErrorTb4b4b4(Ta5d6ff'no URL to reconnect'Tb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3_userClosing Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72await Tff7b72thisTb4b4b4.Te6edf3connectTb4b4b4(Tff7b72thisTb4b4b4.Te6edf3urlTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72async Te6edf3sendTb4b4b4(Te6edf3bytesTb4b4b4)Tb4b4b4{ Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3ws Tff7b72&& Tff7b72thisTb4b4b4.Te6edf3wsTb4b4b4.Te6edf3readyState Tff7b72=== Te6edf3WebSocketTb4b4b4.Te6edf3OPENTb4b4b4) Tff7b72thisTb4b4b4.Te6edf3wsTb4b4b4.Te6edf3sendTb4b4b4(Te6edf3bytesTb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72async Te6edf3disconnectTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3_userClosing Tff7b72= Tff7b72trueTb4b4b4;
Tff7b72try Tb4b4b4{ Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3wsTb4b4b4) Tff7b72thisTb4b4b4.Te6edf3wsTb4b4b4.Te6edf3closeTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4}
Tff7b72thisTb4b4b4.Te6edf3ws Tff7b72= Tff7b72nullTb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3url Tff7b72= Tff7b72nullTb4b4b4;
T8b949e// onclose handler above will fire 'idle' because _userClosing is true.
Tb4b4b4}
T8b949e// See SerialTransport.forceClose — closes the socket but leaves the URL set
T8b949e// so reconnect() can reopen it.
Tff7b72async Te6edf3forceCloseTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3_userClosing Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72try Tb4b4b4{ Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3wsTb4b4b4) Tff7b72thisTb4b4b4.Te6edf3wsTb4b4b4.Te6edf3closeTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4}
T8b949e// ws.onclose will fire 'closed' (because _userClosing was reset to false).
Tb4b4b4}
Tb4b4b4}

T8b949e// ===== RNS-over-MeshChatX transport =====
T8b949e// Bridges the upper-layer KISS-framed Provisioning protocol to MeshChatX's
T8b949e// generic rns.link.* WebSocket API, which terminates on an RNS Link to the
T8b949e// remote node. CMD_PROVISION_REQ frames are unwrapped to rns.link.request
T8b949e// payloads; the request body comes back, gets re-wrapped as CMD_PROVISION_RSP,
T8b949e// and is pushed to onBytes so ProvisioningClient sees the exchange unchanged.
Tff7b72class Te6edf3RnsTransport Tb4b4b4{
Tff7b72constructorTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3ws Tff7b72= Tff7b72nullTb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3params Tff7b72= Tff7b72nullTb4b4b4; T8b949e// { meshchatxUrl, destinationHash, aspect, autoIdentify }
Tff7b72thisTb4b4b4.Te6edf3onBytes Tff7b72= Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{Tb4b4b4}Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3onStatus Tff7b72= Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{Tb4b4b4}Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3_userClosing Tff7b72= Tff7b72falseTb4b4b4;
T8b949e// True once an involuntary close (RNS link_closed broadcast, no_active_link
T8b949e// reply, etc.) has fired _handleInvoluntaryClose — keeps the teardown
T8b949e// path idempotent under racing signals.
Tff7b72thisTb4b4b4.Te6edf3_involuntaryClosed Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3_reqIdCounter Tff7b72= T79c0ff1Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3_waiters Tff7b72= Tff7b72new Tffa657MapTb4b4b4(Tb4b4b4)Tb4b4b4; T8b949e// request_id → { onSuccess(body), onFailure(reason), onPhase?, onProgress? }
Tff7b72thisTb4b4b4.Te6edf3_pingWaiter Tff7b72= Tff7b72nullTb4b4b4; T8b949e// { resolve, reject, timerId } — for ws-verify ping/pong
Tff7b72thisTb4b4b4.Te6edf3_kissOut Tff7b72= Tff7b72new Te6edf3KissDecoderTb4b4b4(Tb4b4b4(Te6edf3cmdTb4b4b4, Te6edf3payloadTb4b4b4) Tb4b4b4=> Tff7b72thisTb4b4b4.Te6edf3_onOutgoingKissFrameTb4b4b4(Te6edf3cmdTb4b4b4, Te6edf3payloadTb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3_unloadHandler Tff7b72= Tff7b72nullTb4b4b4; T8b949e// bound page-unload listener (attached during connect)
T8b949e// Advertised default for ProvisioningClient.request timeouts when this
T8b949e// transport is in use. LoRa Resource transfers commonly take 10-30s for
T8b949e// schemas; the snappy 5s default used on Serial/BLE/WebSocket times out
T8b949e// before the response can land. ProvisioningClient picks this up via
T8b949e// duck-typing if the property is set on the transport.
Tff7b72thisTb4b4b4.Te6edf3defaultRequestTimeoutMs Tff7b72= T79c0ff30000Tb4b4b4;
T8b949e// Bytes are expensive on LoRa — request heatshrink-compressed responses
T8b949e// for bulky ops (schema, state). ProvisioningClient inspects this flag.
Tff7b72thisTb4b4b4.Te6edf3compressionPreferred Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4}

T8b949e// Server phase strings → user-friendly status labels.
Tff7b72static Te6edf3PHASE_LABELS Tff7b72= Tb4b4b4{
Te6edf3finding_pathTff7b72: Ta5d6ff'Finding path'Tb4b4b4,
Te6edf3establishing_linkTff7b72: Ta5d6ff'Establishing link'Tb4b4b4,
Te6edf3identifyingTff7b72: Ta5d6ff'Authenticating'Tb4b4b4,
Tb4b4b4}Tb4b4b4;

T8b949e// Server failure_reason strings → human-friendly error messages.
Tff7b72static Te6edf3FAILURE_LABELS Tff7b72= Tb4b4b4{
Te6edf3no_path_to_destinationTff7b72: Ta5d6ff'No path to destination (no announce received yet?)'Tb4b4b4,
Te6edf3link_establishment_timeoutTff7b72: Ta5d6ff'Link establishment timed out'Tb4b4b4,
Te6edf3no_identity_for_destinationTff7b72: Ta5d6ff'Identity not recalled for destination'Tb4b4b4,
Te6edf3no_local_identityTff7b72: Ta5d6ff'No local identity available on MeshChatX'Tb4b4b4,
Te6edf3no_active_linkTff7b72: Ta5d6ff'Link is not active'Tb4b4b4,
Te6edf3ws_closedTff7b72: Ta5d6ff'WebSocket disconnected'Tb4b4b4,
Te6edf3timeoutTff7b72: Ta5d6ff'Operation timed out'Tb4b4b4,
Te6edf3ws_verify_timeoutTff7b72: Ta5d6ff'MeshChatX did not respond to ping'Tb4b4b4,
Te6edf3missing_destination_or_aspectTff7b72: Ta5d6ff'Missing destination hash or aspect'Tb4b4b4,
Te6edf3invalid_destination_hashTff7b72: Ta5d6ff'Destination hash is not valid hex'Tb4b4b4,
Tb4b4b4}Tb4b4b4;
Tff7b72static Te6edf3_friendlyFailureTb4b4b4(Te6edf3reasonTb4b4b4)Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3reasonTb4b4b4) Tff7b72return Ta5d6ff'failure'Tb4b4b4;
Tff7b72return Te6edf3RnsTransportTb4b4b4.Te6edf3FAILURE_LABELSTb4b4b4[Te6edf3reasonTb4b4b4] Tff7b72|| Te6edf3reasonTb4b4b4;
Tb4b4b4}
Tff7b72static Te6edf3availableTb4b4b4(Tb4b4b4)Tb4b4b4{ Tff7b72return Tff7b72trueTb4b4b4; Tb4b4b4}

Te6edf3_nextReqIdTb4b4b4(Tb4b4b4)Tb4b4b4{ Tff7b72return Tff7b72thisTb4b4b4.Te6edf3_reqIdCounterTff7b72++Tb4b4b4; Tb4b4b4}

Tff7b72static Te6edf3_b64EncodeTb4b4b4(Te6edf3bytesTb4b4b4)Tb4b4b4{
Tff7b72let Te6edf3s Tff7b72= Ta5d6ff''Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72let Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< Te6edf3bytesTb4b4b4.Te6edf3lengthTb4b4b4; Tff7b72++Te6edf3iTb4b4b4) Te6edf3s Tff7b72+= Tffa657StringTb4b4b4.Te6edf3fromCharCodeTb4b4b4(Te6edf3bytesTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4)Tb4b4b4;
Tff7b72return Te6edf3btoaTb4b4b4(Te6edf3sTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72static Te6edf3_b64DecodeTb4b4b4(Te6edf3b64Tb4b4b4)Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3b64Tb4b4b4) Tff7b72return Tff7b72new Tffa657Uint8ArrayTb4b4b4(T79c0ff0Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3s Tff7b72= Te6edf3atobTb4b4b4(Te6edf3b64Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3out Tff7b72= Tff7b72new Tffa657Uint8ArrayTb4b4b4(Te6edf3sTb4b4b4.Te6edf3lengthTb4b4b4)Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72let Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< Te6edf3sTb4b4b4.Te6edf3lengthTb4b4b4; Tff7b72++Te6edf3iTb4b4b4) Te6edf3outTb4b4b4[Te6edf3iTb4b4b4] Tff7b72= Te6edf3sTb4b4b4.Te6edf3charCodeAtTb4b4b4(Te6edf3iTb4b4b4)Tb4b4b4;
Tff7b72return Te6edf3outTb4b4b4;
Tb4b4b4}

Tff7b72async Te6edf3connectTb4b4b4(Te6edf3paramsTb4b4b4)Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3params Tff7b72= Te6edf3paramsTb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3_involuntaryClosed Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72const Tb4b4b4{ Te6edf3meshchatxUrlTb4b4b4, Te6edf3destinationHashTb4b4b4, Te6edf3aspectTb4b4b4, Te6edf3autoIdentify Tb4b4b4} Tff7b72= Te6edf3paramsTb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3meshchatxUrlTb4b4b4) Tff7b72throw Tff7b72new Tf85149ErrorTb4b4b4(Ta5d6ff'missing MeshChatX URL'Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3destinationHash Tff7b72|| Tff7b72!Ta5d6ff/^[0-9a-fA-F]{32}$/Tb4b4b4.Te6edf3testTb4b4b4(Te6edf3destinationHashTb4b4b4)Tb4b4b4)
Tff7b72throw Tff7b72new Tf85149ErrorTb4b4b4(Ta5d6ff'destination hash must be 32 hex characters'Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3aspectTb4b4b4) Tff7b72throw Tff7b72new Tf85149ErrorTb4b4b4(Ta5d6ff'missing aspect'Tb4b4b4)Tb4b4b4;

T8b949e// Stage 1: open the WebSocket to MeshChatX.
Tff7b72thisTb4b4b4.Te6edf3onStatusTb4b4b4(Tb4b4b4{Te6edf3stateTff7b72:Ta5d6ff'connecting'Tb4b4b4, Te6edf3infoTff7b72: Ta5d6ff'WS connecting'Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72await Tff7b72new Tffa657PromiseTb4b4b4(Tb4b4b4(Te6edf3resolveTb4b4b4, Te6edf3rejectTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72try Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3ws Tff7b72= Tff7b72new Te6edf3WebSocketTb4b4b4(Te6edf3meshchatxUrlTb4b4b4)Tb4b4b4;
Tff7b72let Te6edf3opened Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3wsTb4b4b4.Te6edf3onopen Tff7b72= Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Te6edf3opened Tff7b72= Tff7b72trueTb4b4b4;
T8b949e// Attach unload handlers immediately on WS open. From this point on,
T8b949e// a page refresh / tab close can race with an in-flight rns.link.open,
T8b949e// and we want a synchronous best-effort teardown to ride along.
Tff7b72thisTb4b4b4.Te6edf3_attachUnloadHandlersTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3resolveTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3wsTb4b4b4.Te6edf3onmessage Tff7b72= Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4=> Tff7b72thisTb4b4b4.Te6edf3_onWsMessageTb4b4b4(Te6edf3eTb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3wsTb4b4b4.Te6edf3onerror Tff7b72= Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{ Tff7b72if Tb4b4b4(Tff7b72!Te6edf3openedTb4b4b4) Te6edf3rejectTb4b4b4(Tff7b72new Tf85149ErrorTb4b4b4(Ta5d6ff'WebSocket connect failed (check URL / TLS / firewall)'Tb4b4b4)Tb4b4b4)Tb4b4b4; Tb4b4b4}Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3wsTb4b4b4.Te6edf3onclose Tff7b72= Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
T8b949e// Fail any in-flight waiters so callers don't hang.
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3w Tff7b72of Tff7b72thisTb4b4b4.Te6edf3_waitersTb4b4b4.Te6edf3valuesTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{ Tff7b72try Tb4b4b4{ Te6edf3wTb4b4b4.Te6edf3onFailure Tff7b72&& Te6edf3wTb4b4b4.Te6edf3onFailureTb4b4b4(Ta5d6ff'ws_closed'Tb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4} Tb4b4b4}
Tff7b72thisTb4b4b4.Te6edf3_waitersTb4b4b4.Te6edf3clearTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3_pingWaiterTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3w Tff7b72= Tff7b72thisTb4b4b4.Te6edf3_pingWaiterTb4b4b4; Tff7b72thisTb4b4b4.Te6edf3_pingWaiter Tff7b72= Tff7b72nullTb4b4b4;
Tff7b72try Tb4b4b4{ Te6edf3clearTimeoutTb4b4b4(Te6edf3wTb4b4b4.Te6edf3timerIdTb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4}
Tff7b72try Tb4b4b4{ Te6edf3wTb4b4b4.Te6edf3rejectTb4b4b4(Tff7b72new Tf85149ErrorTb4b4b4(Ta5d6ff'ws_closed'Tb4b4b4)Tb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4}
Tb4b4b4}
Tff7b72thisTb4b4b4.Te6edf3_detachUnloadHandlersTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3onStatusTb4b4b4(Tb4b4b4{Te6edf3stateTff7b72: Tff7b72thisTb4b4b4.Te6edf3_userClosing Tff7b72? Ta5d6ff'idle' Tff7b72: Ta5d6ff'closed'Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3onStatusTb4b4b4(Tb4b4b4{Te6edf3stateTff7b72:Ta5d6ff'error'Tb4b4b4, Te6edf3infoTff7b72: Te6edf3eTb4b4b4.Te6edf3messageTb4b4b4}Tb4b4b4)Tb4b4b4; Te6edf3rejectTb4b4b4(Te6edf3eTb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4}Tb4b4b4)Tb4b4b4;

T8b949e// Stage 2: verify the WS is actually a working MeshChatX endpoint
T8b949e// (and not, say, a different server that happens to accept WS upgrades)
T8b949e// by sending a ping and waiting for a pong. Confirms bidirectional
T8b949e// message flow before we commit to the slow Link setup.
Tff7b72thisTb4b4b4.Te6edf3onStatusTb4b4b4(Tb4b4b4{Te6edf3stateTff7b72:Ta5d6ff'connecting'Tb4b4b4, Te6edf3infoTff7b72: Ta5d6ff'WS verifying'Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72try Tb4b4b4{
Tff7b72await Tff7b72thisTb4b4b4.Te6edf3_pingServerTb4b4b4(T79c0ff5000Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3reason Tff7b72= Te6edf3e Tff7b72&& Te6edf3eTb4b4b4.Te6edf3message Tff7b72=== Ta5d6ff'timeout' Tff7b72? Ta5d6ff'ws_verify_timeout' Tff7b72: Tb4b4b4(Te6edf3eTb4b4b4.Te6edf3message Tff7b72|| Ta5d6ff'ws_verify_failed'Tb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3onStatusTb4b4b4(Tb4b4b4{Te6edf3stateTff7b72:Ta5d6ff'error'Tb4b4b4, Te6edf3infoTff7b72: Te6edf3RnsTransportTb4b4b4.Te6edf3_friendlyFailureTb4b4b4(Te6edf3reasonTb4b4b4)Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72try Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3ws Tff7b72&& Tff7b72thisTb4b4b4.Te6edf3wsTb4b4b4.Te6edf3closeTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4}
Tff7b72throw Tff7b72new Tf85149ErrorTb4b4b4(Te6edf3reasonTb4b4b4)Tb4b4b4;
Tb4b4b4}

T8b949e// Stage 3: open the Link (and optionally identify) via the MeshChatX backend.
T8b949e// The server emits 'phase' events as it makes progress through path discovery,
T8b949e// link establishment, and identification — surface them as their friendly labels.
Tff7b72thisTb4b4b4.Te6edf3onStatusTb4b4b4(Tb4b4b4{Te6edf3stateTff7b72:Ta5d6ff'connecting'Tb4b4b4, Te6edf3infoTff7b72: Ta5d6ff'Link connecting'Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72try Tb4b4b4{
Tff7b72const Te6edf3result Tff7b72= Tff7b72await Tff7b72thisTb4b4b4.Te6edf3_sendAndWaitTb4b4b4(Ta5d6ff'rns.link.open'Tb4b4b4, Tb4b4b4{
Te6edf3destination_hashTff7b72: Te6edf3destinationHashTb4b4b4.Te6edf3toLowerCaseTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3aspectTb4b4b4,
Te6edf3auto_identifyTff7b72: Tff7b72!Tff7b72!Te6edf3autoIdentifyTb4b4b4,
Tb4b4b4}Tb4b4b4, Tb4b4b4{
T8b949e// Idle-timer resets on each phase event (finding_path →
T8b949e// establishing_link → identifying), so a server making progress won't
T8b949e// trip this even on slow LoRa.
Te6edf3timeoutMsTff7b72: T79c0ff30000Tb4b4b4,
Te6edf3onPhaseTff7b72: Tb4b4b4(Te6edf3phaseTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3label Tff7b72= Te6edf3RnsTransportTb4b4b4.Te6edf3PHASE_LABELSTb4b4b4[Te6edf3phaseTb4b4b4] Tff7b72|| Te6edf3phaseTb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3onStatusTb4b4b4(Tb4b4b4{Te6edf3stateTff7b72:Ta5d6ff'connecting'Tb4b4b4, Te6edf3infoTff7b72: Te6edf3labelTb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3ident Tff7b72= Te6edf3result Tff7b72&& Te6edf3resultTb4b4b4.Te6edf3identified Tff7b72? Ta5d6ff' (identified)' Tff7b72: Ta5d6ff''Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3onStatusTb4b4b4(Tb4b4b4{Te6edf3stateTff7b72:Ta5d6ff'connected'Tb4b4b4, Te6edf3infoTff7b72: Te6edf3aspect Tff7b72+ Ta5d6ff' @ ' Tff7b72+ Te6edf3destinationHashTb4b4b4.Te6edf3sliceTb4b4b4(T79c0ff0Tb4b4b4,T79c0ff8Tb4b4b4) Tff7b72+ Te6edf3identTb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3reason Tff7b72= Tb4b4b4(Te6edf3e Tff7b72&& Te6edf3eTb4b4b4.Te6edf3messageTb4b4b4) Tff7b72|| Ta5d6ff'failure'Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3onStatusTb4b4b4(Tb4b4b4{Te6edf3stateTff7b72:Ta5d6ff'error'Tb4b4b4, Te6edf3infoTff7b72: Te6edf3RnsTransportTb4b4b4.Te6edf3_friendlyFailureTb4b4b4(Te6edf3reasonTb4b4b4)Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72try Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3ws Tff7b72&& Tff7b72thisTb4b4b4.Te6edf3wsTb4b4b4.Te6edf3closeTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4}
Tff7b72throw Te6edf3eTb4b4b4;
Tb4b4b4}
Tb4b4b4}

T8b949e// Best-effort synchronous teardown when the page is being unloaded
T8b949e// (reload, tab close, navigation). Without this, the server keeps polling
T8b949e// path-discovery / link-establishment for an in-flight rns.link.open, may
T8b949e// cache a half-finished link, and emits broadcast events to a renderer
T8b949e// that's already torn down. We can't await here — the page is dying — but
T8b949e// browsers do flush queued WebSocket frames before the connection terminates,
T8b949e// so a fire-and-forget rns.link.close + a clean WebSocket.close(1000) gets the
T8b949e// message to the server in practice.
Te6edf3_attachUnloadHandlersTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3_unloadHandlerTb4b4b4) Tff7b72returnTb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3_unloadHandler Tff7b72= Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72try Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3ws Tff7b72&& Tff7b72thisTb4b4b4.Te6edf3wsTb4b4b4.Te6edf3readyState Tff7b72=== Te6edf3WebSocketTb4b4b4.Te6edf3OPEN Tff7b72&& Tff7b72thisTb4b4b4.Te6edf3paramsTb4b4b4) Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3wsTb4b4b4.Te6edf3sendTb4b4b4(Tffa657JSONTb4b4b4.Te6edf3stringifyTb4b4b4(Tb4b4b4{
Te6edf3typeTff7b72: Ta5d6ff'rns.link.close'Tb4b4b4,
Te6edf3request_idTff7b72: Tff7b72thisTb4b4b4.Te6edf3_nextReqIdTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3destination_hashTff7b72: Tff7b72thisTb4b4b4.Te6edf3paramsTb4b4b4.Te6edf3destinationHashTb4b4b4.Te6edf3toLowerCaseTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3aspectTff7b72: Tff7b72thisTb4b4b4.Te6edf3paramsTb4b4b4.Te6edf3aspectTb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4)Tb4b4b4;
T8b949e// Status 1000 = normal closure. Without this the browser may emit
T8b949e// an abnormal-close (1006) which the server can't distinguish from a
T8b949e// network error.
Tff7b72thisTb4b4b4.Te6edf3wsTb4b4b4.Te6edf3closeTb4b4b4(T79c0ff1000Tb4b4b4, Ta5d6ff'page-unload'Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{ T8b949e/* page is dying; nothing useful to do */ Tb4b4b4}
Tb4b4b4}Tb4b4b4;
Tffa657windowTb4b4b4.Te6edf3addEventListenerTb4b4b4(Ta5d6ff'beforeunload'Tb4b4b4, Tff7b72thisTb4b4b4.Te6edf3_unloadHandlerTb4b4b4)Tb4b4b4;
Tffa657windowTb4b4b4.Te6edf3addEventListenerTb4b4b4(Ta5d6ff'pagehide'Tb4b4b4, Tff7b72thisTb4b4b4.Te6edf3_unloadHandlerTb4b4b4)Tb4b4b4;
Tb4b4b4}

Te6edf3_detachUnloadHandlersTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Tff7b72thisTb4b4b4.Te6edf3_unloadHandlerTb4b4b4) Tff7b72returnTb4b4b4;
Tffa657windowTb4b4b4.Te6edf3removeEventListenerTb4b4b4(Ta5d6ff'beforeunload'Tb4b4b4, Tff7b72thisTb4b4b4.Te6edf3_unloadHandlerTb4b4b4)Tb4b4b4;
Tffa657windowTb4b4b4.Te6edf3removeEventListenerTb4b4b4(Ta5d6ff'pagehide'Tb4b4b4, Tff7b72thisTb4b4b4.Te6edf3_unloadHandlerTb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3_unloadHandler Tff7b72= Tff7b72nullTb4b4b4;
Tb4b4b4}

T8b949e// Send a {type:"ping"} JSON frame and wait for the matching {type:"pong"}.
T8b949e// MeshChatX's main /ws bus has supported this since the WebSocket API was
T8b949e// documented (meshchatx_api.md §2.1).
Te6edf3_pingServerTb4b4b4(Te6edf3timeoutMsTb4b4b4)Tb4b4b4{
Tff7b72return Tff7b72new Tffa657PromiseTb4b4b4(Tb4b4b4(Te6edf3resolveTb4b4b4, Te6edf3rejectTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3timerId Tff7b72= Te6edf3setTimeoutTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3_pingWaiter Tff7b72&& Tff7b72thisTb4b4b4.Te6edf3_pingWaiterTb4b4b4.Te6edf3timerId Tff7b72=== Te6edf3timerIdTb4b4b4) Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3_pingWaiter Tff7b72= Tff7b72nullTb4b4b4;
Te6edf3rejectTb4b4b4(Tff7b72new Tf85149ErrorTb4b4b4(Ta5d6ff'timeout'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4, Te6edf3timeoutMsTb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3_pingWaiter Tff7b72= Tb4b4b4{ Te6edf3resolveTb4b4b4, Te6edf3rejectTb4b4b4, Te6edf3timerId Tb4b4b4}Tb4b4b4;
Tff7b72try Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3wsTb4b4b4.Te6edf3sendTb4b4b4(Tffa657JSONTb4b4b4.Te6edf3stringifyTb4b4b4(Tb4b4b4{Te6edf3typeTff7b72:Ta5d6ff'ping'Tb4b4b4}Tb4b4b4)Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{
Te6edf3clearTimeoutTb4b4b4(Te6edf3timerIdTb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3_pingWaiter Tff7b72= Tff7b72nullTb4b4b4;
Te6edf3rejectTb4b4b4(Te6edf3eTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}

Tff7b72async Te6edf3reconnectTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Tff7b72thisTb4b4b4.Te6edf3paramsTb4b4b4) Tff7b72throw Tff7b72new Tf85149ErrorTb4b4b4(Ta5d6ff'no params to reconnect'Tb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3_userClosing Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72await Tff7b72thisTb4b4b4.Te6edf3connectTb4b4b4(Tff7b72thisTb4b4b4.Te6edf3paramsTb4b4b4)Tb4b4b4;
Tb4b4b4}

T8b949e// The upper layer hands us KISS bytes. Decode the frame; if it's a
T8b949e// PROVISION_REQ, unwrap it onto rns.link.request. Other opcodes are silently
T8b949e// dropped (legacy KISS / CMD_RESET / etc are not transported over this link).
Tff7b72async Te6edf3sendTb4b4b4(Te6edf3bytesTb4b4b4)Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3_kissOutTb4b4b4.Te6edf3feedTb4b4b4(Te6edf3bytesTb4b4b4)Tb4b4b4;
Tb4b4b4}

Te6edf3_onOutgoingKissFrameTb4b4b4(Te6edf3cmdTb4b4b4, Te6edf3payloadTb4b4b4)Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3cmd Tff7b72!== Te6edf3CMD_PROVISION_REQTb4b4b4) Tff7b72returnTb4b4b4;
Tff7b72const Tb4b4b4{ Te6edf3destinationHashTb4b4b4, Te6edf3aspect Tb4b4b4} Tff7b72= Tff7b72thisTb4b4b4.Te6edf3paramsTb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3_sendAndWaitTb4b4b4(Ta5d6ff'rns.link.request'Tb4b4b4, Tb4b4b4{
Te6edf3destination_hashTff7b72: Te6edf3destinationHashTb4b4b4.Te6edf3toLowerCaseTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3aspectTb4b4b4,
Te6edf3pathTff7b72: Ta5d6ff'/provision'Tb4b4b4,
Te6edf3data_b64Tff7b72: Te6edf3RnsTransportTb4b4b4.Te6edf3_b64EncodeTb4b4b4(Te6edf3payloadTb4b4b4)Tb4b4b4,
Tb4b4b4}Tb4b4b4, Tb4b4b4{
Te6edf3onSuccessTff7b72: Tb4b4b4(Te6edf3bodyTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3respPayload Tff7b72= Te6edf3RnsTransportTb4b4b4.Te6edf3_b64DecodeTb4b4b4(Te6edf3bodyTb4b4b4.Te6edf3body_b64 Tff7b72|| Ta5d6ff''Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3frame Tff7b72= Te6edf3kissEncodeTb4b4b4(Te6edf3CMD_PROVISION_RSPTb4b4b4, Te6edf3respPayloadTb4b4b4)Tb4b4b4;
Tff7b72try Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3onBytesTb4b4b4(Te6edf3frameTb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4}
Tb4b4b4}Tb4b4b4,
T8b949e// Generic failures (timeout, etc.) drop — ProvisioningClient's own
T8b949e// request timeout rejects the caller cleanly. But 'no_active_link' is
T8b949e// MeshChatX's authoritative "this link is gone" reply: fast-path the
T8b949e// transport into the involuntary-close teardown so we surface the drop
T8b949e// and (if autoReconnect is on) kick startReconnect right away, rather
T8b949e// than waiting for the broadcast / per-request UI timeout. 'ws_closed'
T8b949e// is belt-and-suspenders against ws.onclose racing with an in-flight
T8b949e// waiter — _handleInvoluntaryClose is idempotent.
Te6edf3onFailureTff7b72: Tb4b4b4(Te6edf3reasonTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3reason Tff7b72=== Ta5d6ff'no_active_link' Tff7b72|| Te6edf3reason Tff7b72=== Ta5d6ff'ws_closed'Tb4b4b4) Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3_handleInvoluntaryCloseTb4b4b4(Te6edf3reasonTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}

Tff7b72async Te6edf3disconnectTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3_userClosing Tff7b72= Tff7b72trueTb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3ws Tff7b72&& Tff7b72thisTb4b4b4.Te6edf3wsTb4b4b4.Te6edf3readyState Tff7b72=== Te6edf3WebSocketTb4b4b4.Te6edf3OPEN Tff7b72&& Tff7b72thisTb4b4b4.Te6edf3paramsTb4b4b4) Tb4b4b4{
Tff7b72try Tb4b4b4{
Tff7b72await Tff7b72thisTb4b4b4.Te6edf3_sendAndWaitTb4b4b4(Ta5d6ff'rns.link.close'Tb4b4b4, Tb4b4b4{
Te6edf3destination_hashTff7b72: Tff7b72thisTb4b4b4.Te6edf3paramsTb4b4b4.Te6edf3destinationHashTb4b4b4.Te6edf3toLowerCaseTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3aspectTff7b72: Tff7b72thisTb4b4b4.Te6edf3paramsTb4b4b4.Te6edf3aspectTb4b4b4,
Tb4b4b4}Tb4b4b4, Tb4b4b4{Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4}
Tb4b4b4}
Tff7b72try Tb4b4b4{ Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3wsTb4b4b4) Tff7b72thisTb4b4b4.Te6edf3wsTb4b4b4.Te6edf3closeTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4}
Tff7b72thisTb4b4b4.Te6edf3ws Tff7b72= Tff7b72nullTb4b4b4;
Tb4b4b4}

Tff7b72async Te6edf3forceCloseTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3_userClosing Tff7b72= Tff7b72falseTb4b4b4;
T8b949e// Evict MeshChatX's cached link for our (aspect, destination_hash) before
T8b949e// tearing down the WS. MeshChatX caches by remote, not by client, and
T8b949e// reuses the cache on the next rns.link.open until its own keepalive
T8b949e// expires — so after a remote Reboot the rebuilt session would otherwise
T8b949e// inherit a stale link that's already dead on the RNS side. Fire-and-
T8b949e// forget: browsers flush queued WS frames before close (same pattern as
T8b949e// the page-unload handler above), so the close request reaches MeshChatX
T8b949e// and we don't have to block on a reply we don't need.
Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3ws Tff7b72&& Tff7b72thisTb4b4b4.Te6edf3wsTb4b4b4.Te6edf3readyState Tff7b72=== Te6edf3WebSocketTb4b4b4.Te6edf3OPEN Tff7b72&& Tff7b72thisTb4b4b4.Te6edf3paramsTb4b4b4) Tb4b4b4{
Tff7b72try Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3wsTb4b4b4.Te6edf3sendTb4b4b4(Tffa657JSONTb4b4b4.Te6edf3stringifyTb4b4b4(Tb4b4b4{
Te6edf3typeTff7b72: Ta5d6ff'rns.link.close'Tb4b4b4,
Te6edf3request_idTff7b72: Tff7b72thisTb4b4b4.Te6edf3_nextReqIdTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3destination_hashTff7b72: Tff7b72thisTb4b4b4.Te6edf3paramsTb4b4b4.Te6edf3destinationHashTb4b4b4.Te6edf3toLowerCaseTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3aspectTff7b72: Tff7b72thisTb4b4b4.Te6edf3paramsTb4b4b4.Te6edf3aspectTb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4}
Tb4b4b4}
Tff7b72try Tb4b4b4{ Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3wsTb4b4b4) Tff7b72thisTb4b4b4.Te6edf3wsTb4b4b4.Te6edf3closeTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4}
Tb4b4b4}

T8b949e// Fired when the RNS Link or the underlying WS goes down without us asking
T8b949e// (MeshChatX link_closed broadcast, no_active_link reply on a request, etc).
T8b949e// Fails in-flight waiters immediately so callers don't sit on a 30s
T8b949e// ProvisioningClient timeout, then closes the WS — ws.onclose is what
T8b949e// actually emits 'closed' onStatus (since _userClosing stays false), which
T8b949e// routes through onTransportStatus to startReconnect when autoReconnect is
T8b949e// on. Idempotent so concurrent signals (broadcast + request failure +
T8b949e// ws.onclose racing during a remote reboot) collapse to one teardown.
Te6edf3_handleInvoluntaryCloseTb4b4b4(Te6edf3reasonTb4b4b4)Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3_involuntaryClosedTb4b4b4) Tff7b72returnTb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3_involuntaryClosed Tff7b72= Tff7b72trueTb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3w Tff7b72of Tff7b72thisTb4b4b4.Te6edf3_waitersTb4b4b4.Te6edf3valuesTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72try Tb4b4b4{ Te6edf3wTb4b4b4.Te6edf3onFailure Tff7b72&& Te6edf3wTb4b4b4.Te6edf3onFailureTb4b4b4(Te6edf3reasonTb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4}
Tb4b4b4}
Tff7b72thisTb4b4b4.Te6edf3_waitersTb4b4b4.Te6edf3clearTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72try Tb4b4b4{ Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3wsTb4b4b4) Tff7b72thisTb4b4b4.Te6edf3wsTb4b4b4.Te6edf3closeTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4}
Tb4b4b4}

T8b949e// Send a JSON command and return a promise that resolves on the matching
T8b949e// {status:"success"} frame and rejects on {status:"failure"} or after
T8b949e// timeoutMs of idle (phase/progress events count as activity and reset the
T8b949e// idle timer). Optional onPhase/onProgress callbacks consume intermediate
T8b949e// frames.
Te6edf3_sendAndWaitTb4b4b4(Te6edf3typeTb4b4b4, Te6edf3bodyTb4b4b4, Tb4b4b4{ Te6edf3onPhaseTb4b4b4, Te6edf3onProgressTb4b4b4, Te6edf3onSuccessTb4b4b4, Te6edf3onFailureTb4b4b4, Te6edf3timeoutMs Tff7b72= T79c0ff15000 Tb4b4b4} Tff7b72= Tb4b4b4{Tb4b4b4}Tb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3request_id Tff7b72= Tff7b72thisTb4b4b4.Te6edf3_nextReqIdTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3frame Tff7b72= Tffa657ObjectTb4b4b4.Te6edf3assignTb4b4b4(Tb4b4b4{ Te6edf3typeTb4b4b4, Te6edf3request_id Tb4b4b4}Tb4b4b4, Te6edf3bodyTb4b4b4)Tb4b4b4;
Tff7b72return Tff7b72new Tffa657PromiseTb4b4b4(Tb4b4b4(Te6edf3resolveTb4b4b4, Te6edf3rejectTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72let Te6edf3timerId Tff7b72= Tff7b72nullTb4b4b4;
Tff7b72const Te6edf3armTimer Tff7b72= Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3timerId Tff7b72!== Tff7b72nullTb4b4b4) Te6edf3clearTimeoutTb4b4b4(Te6edf3timerIdTb4b4b4)Tb4b4b4;
Te6edf3timerId Tff7b72= Te6edf3setTimeoutTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Tff7b72thisTb4b4b4.Te6edf3_waitersTb4b4b4.Te6edf3hasTb4b4b4(Te6edf3request_idTb4b4b4)Tb4b4b4) Tff7b72returnTb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3_waitersTb4b4b4.Tff7b72deleteTb4b4b4(Te6edf3request_idTb4b4b4)Tb4b4b4;
Tff7b72try Tb4b4b4{ Te6edf3onFailure Tff7b72&& Te6edf3onFailureTb4b4b4(Ta5d6ff'timeout'Tb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4}
Te6edf3rejectTb4b4b4(Tff7b72new Tf85149ErrorTb4b4b4(Te6edf3type Tff7b72+ Ta5d6ff' timeout after ' Tff7b72+ Te6edf3timeoutMs Tff7b72+ Ta5d6ff'ms'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4, Te6edf3timeoutMsTb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3_waitersTb4b4b4.Te6edf3setTb4b4b4(Te6edf3request_idTb4b4b4, Tb4b4b4{
Te6edf3onPhaseTff7b72: Tb4b4b4(Te6edf3pTb4b4b4) Tb4b4b4=> Tb4b4b4{ Te6edf3armTimerTb4b4b4(Tb4b4b4)Tb4b4b4; Tff7b72if Tb4b4b4(Te6edf3onPhaseTb4b4b4) Tff7b72try Tb4b4b4{ Te6edf3onPhaseTb4b4b4(Te6edf3pTb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4} Tb4b4b4}Tb4b4b4,
Te6edf3onProgressTff7b72: Tb4b4b4(Te6edf3prTb4b4b4) Tb4b4b4=> Tb4b4b4{ Te6edf3armTimerTb4b4b4(Tb4b4b4)Tb4b4b4; Tff7b72if Tb4b4b4(Te6edf3onProgressTb4b4b4) Tff7b72try Tb4b4b4{ Te6edf3onProgressTb4b4b4(Te6edf3prTb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4} Tb4b4b4}Tb4b4b4,
Te6edf3onSuccessTff7b72: Tb4b4b4(Te6edf3msgTb4b4b4) Tb4b4b4=> Tb4b4b4{ Tff7b72if Tb4b4b4(Te6edf3timerId Tff7b72!== Tff7b72nullTb4b4b4) Te6edf3clearTimeoutTb4b4b4(Te6edf3timerIdTb4b4b4)Tb4b4b4; Tff7b72if Tb4b4b4(Te6edf3onSuccessTb4b4b4) Tff7b72try Tb4b4b4{ Te6edf3onSuccessTb4b4b4(Te6edf3msgTb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4} Te6edf3resolveTb4b4b4(Te6edf3msgTb4b4b4)Tb4b4b4; Tb4b4b4}Tb4b4b4,
Te6edf3onFailureTff7b72: Tb4b4b4(Te6edf3reasonTb4b4b4) Tb4b4b4=> Tb4b4b4{ Tff7b72if Tb4b4b4(Te6edf3timerId Tff7b72!== Tff7b72nullTb4b4b4) Te6edf3clearTimeoutTb4b4b4(Te6edf3timerIdTb4b4b4)Tb4b4b4; Tff7b72if Tb4b4b4(Te6edf3onFailureTb4b4b4) Tff7b72try Tb4b4b4{ Te6edf3onFailureTb4b4b4(Te6edf3reasonTb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4} Te6edf3rejectTb4b4b4(Tff7b72new Tf85149ErrorTb4b4b4(Te6edf3reason Tff7b72|| Ta5d6ff'failure'Tb4b4b4)Tb4b4b4)Tb4b4b4; Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72try Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3wsTb4b4b4.Te6edf3sendTb4b4b4(Tffa657JSONTb4b4b4.Te6edf3stringifyTb4b4b4(Te6edf3frameTb4b4b4)Tb4b4b4)Tb4b4b4; Te6edf3armTimerTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Tff7b72if Tb4b4b4(Te6edf3timerId Tff7b72!== Tff7b72nullTb4b4b4) Te6edf3clearTimeoutTb4b4b4(Te6edf3timerIdTb4b4b4)Tb4b4b4; Tff7b72thisTb4b4b4.Te6edf3_waitersTb4b4b4.Tff7b72deleteTb4b4b4(Te6edf3request_idTb4b4b4)Tb4b4b4; Te6edf3rejectTb4b4b4(Te6edf3eTb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}

Te6edf3_onWsMessageTb4b4b4(Te6edf3eTb4b4b4)Tb4b4b4{
Tff7b72let Te6edf3msgTb4b4b4;
Tff7b72try Tb4b4b4{ Te6edf3msg Tff7b72= Tffa657JSONTb4b4b4.Te6edf3parseTb4b4b4(Tff7b72typeof Te6edf3eTb4b4b4.Te6edf3data Tff7b72=== Ta5d6ff'string' Tff7b72? Te6edf3eTb4b4b4.Te6edf3data Tff7b72: Tff7b72new Te6edf3TextDecoderTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3decodeTb4b4b4(Te6edf3eTb4b4b4.Te6edf3dataTb4b4b4)Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72catch Tb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{ Tff7b72returnTb4b4b4; Tb4b4b4}
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3msg Tff7b72|| Tff7b72typeof Te6edf3msgTb4b4b4.Te6edf3type Tff7b72!== Ta5d6ff'string'Tb4b4b4) Tff7b72returnTb4b4b4;

T8b949e// ws-verify ping/pong (used during connect() stage 2).
Tff7b72if Tb4b4b4(Te6edf3msgTb4b4b4.Te6edf3type Tff7b72=== Ta5d6ff'pong'Tb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3w Tff7b72= Tff7b72thisTb4b4b4.Te6edf3_pingWaiterTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3wTb4b4b4) Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3_pingWaiter Tff7b72= Tff7b72nullTb4b4b4; Tff7b72try Tb4b4b4{ Te6edf3clearTimeoutTb4b4b4(Te6edf3wTb4b4b4.Te6edf3timerIdTb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4} Te6edf3wTb4b4b4.Te6edf3resolveTb4b4b4(Te6edf3msgTb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72returnTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3msgTb4b4b4.Te6edf3typeTb4b4b4.Te6edf3startsWithTb4b4b4(Ta5d6ff'rns.link.'Tb4b4b4)Tb4b4b4) Tff7b72returnTb4b4b4; T8b949e// ignore other broadcasts (config, announce, …)

T8b949e// Async server-pushed events (no request_id correlation). MeshChatX fires
T8b949e// rns.link.event { event: 'link_closed' } from RNS's link_closed_callback —
T8b949e// so it covers remote teardowns, RNS-detected link timeouts (e.g. after a
T8b949e// remote reboot), and our own teardown alike. (packet_received variants
T8b949e// are out of scope — Provisioning is request/response, so unsolicited
T8b949e// packets have no consumer yet.)
Tff7b72if Tb4b4b4(Te6edf3msgTb4b4b4.Te6edf3type Tff7b72=== Ta5d6ff'rns.link.event'Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3msgTb4b4b4.Te6edf3event Tff7b72!== Ta5d6ff'link_closed'Tb4b4b4) Tff7b72returnTb4b4b4;
T8b949e// The broadcast bus is per-MeshChatX-instance: events for other links
T8b949e// (different destination_hash / aspect) share it, so filter to ours.
Tff7b72const Te6edf3dh Tff7b72= Tb4b4b4(Te6edf3msgTb4b4b4.Te6edf3destination_hash Tff7b72|| Ta5d6ff''Tb4b4b4)Tb4b4b4.Te6edf3toLowerCaseTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3wantDh Tff7b72= Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3params Tff7b72&& Tff7b72thisTb4b4b4.Te6edf3paramsTb4b4b4.Te6edf3destinationHash Tff7b72|| Ta5d6ff''Tb4b4b4)Tb4b4b4.Te6edf3toLowerCaseTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3wantDh Tff7b72|| Te6edf3dh Tff7b72!== Te6edf3wantDhTb4b4b4) Tff7b72returnTb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3params Tff7b72&& Te6edf3msgTb4b4b4.Te6edf3aspect Tff7b72!== Tff7b72thisTb4b4b4.Te6edf3paramsTb4b4b4.Te6edf3aspectTb4b4b4) Tff7b72returnTb4b4b4;
T8b949e// Suppress for our own disconnect() — link_closed fires for our
T8b949e// outbound rns.link.close too, and we don't want auto-reconnect to
T8b949e// engage after the user clicked Disconnect.
Tff7b72if Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3_userClosingTb4b4b4) Tff7b72returnTb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3_handleInvoluntaryCloseTb4b4b4(Ta5d6ff'link_closed'Tb4b4b4)Tb4b4b4;
Tff7b72returnTb4b4b4;
Tb4b4b4}

Tff7b72const Te6edf3w Tff7b72= Tff7b72thisTb4b4b4.Te6edf3_waitersTb4b4b4.Te6edf3getTb4b4b4(Te6edf3msgTb4b4b4.Te6edf3request_idTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3wTb4b4b4) Tff7b72returnTb4b4b4;
Tff7b72const Te6edf3status Tff7b72= Te6edf3msgTb4b4b4.Te6edf3statusTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3status Tff7b72=== Ta5d6ff'phase'Tb4b4b4) Tb4b4b4{ Tff7b72if Tb4b4b4(Te6edf3wTb4b4b4.Te6edf3onPhaseTb4b4b4) Tff7b72try Tb4b4b4{ Te6edf3wTb4b4b4.Te6edf3onPhaseTb4b4b4(Te6edf3msgTb4b4b4.Te6edf3phaseTb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4} Tff7b72returnTb4b4b4; Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3status Tff7b72=== Ta5d6ff'progress'Tb4b4b4) Tb4b4b4{ Tff7b72if Tb4b4b4(Te6edf3wTb4b4b4.Te6edf3onProgressTb4b4b4) Tff7b72try Tb4b4b4{ Te6edf3wTb4b4b4.Te6edf3onProgressTb4b4b4(Te6edf3msgTb4b4b4.Te6edf3progressTb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4} Tff7b72returnTb4b4b4; Tb4b4b4}
T8b949e// Terminal frame — drop the waiter.
Tff7b72thisTb4b4b4.Te6edf3_waitersTb4b4b4.Tff7b72deleteTb4b4b4(Te6edf3msgTb4b4b4.Te6edf3request_idTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3status Tff7b72=== Ta5d6ff'success'Tb4b4b4) Tb4b4b4{ Te6edf3wTb4b4b4.Te6edf3onSuccessTb4b4b4(Te6edf3msgTb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72else Tb4b4b4{ Te6edf3wTb4b4b4.Te6edf3onFailureTb4b4b4(Te6edf3msgTb4b4b4.Te6edf3failure_reason Tff7b72|| Ta5d6ff'failure'Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

T8b949e// ===== Schema cache helpers =====
T8b949e// Schemas are content-addressed by the firmware's CRC32 hash (info.schemaHash),
T8b949e// so two devices reporting the same hash share the same cached entry. We cap
T8b949e// the total number of cached schemas at SCHEMA_CACHE_MAX to bound storage
T8b949e// growth as a user connects to many devices over time.
Tff7b72const Te6edf3SCHEMA_CACHE_PREFIX Tff7b72= Ta5d6ff'mrf_schema_v'Tb4b4b4;
Tff7b72const Te6edf3SCHEMA_CACHE_MAX Tff7b72= T79c0ff5Tb4b4b4;

T8b949e// Convert Uint8Array (bytes-typed defaults) to a JSON-safe tagged form. Most
T8b949e// schema fields are plain primitives, so this is rarely needed in practice.
Tff7b72function Te6edf3_schemaJsonReplacerTb4b4b4(Te6edf3_kTb4b4b4, Te6edf3vTb4b4b4)Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3v Tff7b72&& Te6edf3vTb4b4b4.Tff7b72constructor Tff7b72=== Tffa657Uint8ArrayTb4b4b4) Tb4b4b4{
Tff7b72let Te6edf3s Tff7b72= Ta5d6ff''Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72let Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< Te6edf3vTb4b4b4.Te6edf3lengthTb4b4b4; Te6edf3iTff7b72++Tb4b4b4) Te6edf3s Tff7b72+= Tffa657StringTb4b4b4.Te6edf3fromCharCodeTb4b4b4(Te6edf3vTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4)Tb4b4b4;
Tff7b72return Tb4b4b4{ Te6edf3__u8Tff7b72: Te6edf3btoaTb4b4b4(Te6edf3sTb4b4b4) Tb4b4b4}Tb4b4b4;
Tb4b4b4}
Tff7b72return Te6edf3vTb4b4b4;
Tb4b4b4}
Tff7b72function Te6edf3_schemaJsonReviverTb4b4b4(Te6edf3_kTb4b4b4, Te6edf3vTb4b4b4)Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3v Tff7b72&& Tff7b72typeof Te6edf3v Tff7b72=== Ta5d6ff'object' Tff7b72&& Tff7b72typeof Te6edf3vTb4b4b4.Te6edf3__u8 Tff7b72=== Ta5d6ff'string' Tff7b72&& Tffa657ObjectTb4b4b4.Te6edf3keysTb4b4b4(Te6edf3vTb4b4b4)Tb4b4b4.Te6edf3length Tff7b72=== T79c0ff1Tb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3s Tff7b72= Te6edf3atobTb4b4b4(Te6edf3vTb4b4b4.Te6edf3__u8Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3out Tff7b72= Tff7b72new Tffa657Uint8ArrayTb4b4b4(Te6edf3sTb4b4b4.Te6edf3lengthTb4b4b4)Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72let Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< Te6edf3sTb4b4b4.Te6edf3lengthTb4b4b4; Te6edf3iTff7b72++Tb4b4b4) Te6edf3outTb4b4b4[Te6edf3iTb4b4b4] Tff7b72= Te6edf3sTb4b4b4.Te6edf3charCodeAtTb4b4b4(Te6edf3iTb4b4b4) Tff7b72& T79c0ff0xffTb4b4b4;
Tff7b72return Te6edf3outTb4b4b4;
Tb4b4b4}
Tff7b72return Te6edf3vTb4b4b4;
Tb4b4b4}
Tff7b72function Te6edf3_schemaSerializeTb4b4b4(Te6edf3schemaTb4b4b4)Tb4b4b4{
Tff7b72return Tffa657JSONTb4b4b4.Te6edf3stringifyTb4b4b4(Te6edf3schemaTb4b4b4, Te6edf3_schemaJsonReplacerTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72function Te6edf3_schemaDeserializeTb4b4b4(Te6edf3strTb4b4b4)Tb4b4b4{
Tff7b72return Tffa657JSONTb4b4b4.Te6edf3parseTb4b4b4(Te6edf3strTb4b4b4, Te6edf3_schemaJsonReviverTb4b4b4)Tb4b4b4;
Tb4b4b4}
T8b949e// Evict the oldest entries to keep cache size bounded. Called before writing
T8b949e// a new key; the `keepKey` arg ensures we don't evict the entry we're about
T8b949e// to write if it already exists (LRU-bump semantics).
Tff7b72function Te6edf3_schemaCachePruneTb4b4b4(Te6edf3keepKeyTb4b4b4)Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Tffa657windowTb4b4b4.Te6edf3localStorageTb4b4b4) Tff7b72returnTb4b4b4;
Tff7b72const Te6edf3keys Tff7b72= Tb4b4b4[Tb4b4b4]Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72let Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< Te6edf3localStorageTb4b4b4.Te6edf3lengthTb4b4b4; Te6edf3iTff7b72++Tb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3k Tff7b72= Te6edf3localStorageTb4b4b4.Te6edf3keyTb4b4b4(Te6edf3iTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3k Tff7b72&& Te6edf3kTb4b4b4.Te6edf3startsWithTb4b4b4(Te6edf3SCHEMA_CACHE_PREFIXTb4b4b4) Tff7b72&& Te6edf3k Tff7b72!== Te6edf3keepKeyTb4b4b4) Te6edf3keysTb4b4b4.Te6edf3pushTb4b4b4(Te6edf3kTb4b4b4)Tb4b4b4;
Tb4b4b4}
T8b949e// localStorage doesn't expose write order, so eviction is approximate —
T8b949e// we drop in iteration order until under the cap. Good enough for an
T8b949e// O(<=5) cache that's only churned when a user touches many devices.
Tff7b72while Tb4b4b4(Te6edf3keysTb4b4b4.Te6edf3length Tff7b72>= Te6edf3SCHEMA_CACHE_MAXTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3victim Tff7b72= Te6edf3keysTb4b4b4.Te6edf3shiftTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72try Tb4b4b4{ Te6edf3localStorageTb4b4b4.Te6edf3removeItemTb4b4b4(Te6edf3victimTb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

T8b949e// ===== heatshrink decoder =====
T8b949e// Minimal LZSS decoder matching the firmware's heatshrink_encoder output.
T8b949e// Static config must agree with the build flags in platformio.ini —
T8b949e// changing HS_WINDOW_BITS / HS_LOOKAHEAD_BITS here without matching the
T8b949e// firmware will silently corrupt every decode.
T8b949e//
T8b949e// Token layout (MSB-first within each byte):
T8b949e// 1 tag bit:
T8b949e// '1' followed by 8 bits → literal byte
T8b949e// '0' followed by (window_bits + lookahead_bits) → backref { offset+1, length+2 }
T8b949e// EOF detection: stop when we can't read the next tag bit (out of input).
Tff7b72function Te6edf3heatshrinkDecodeTb4b4b4(Te6edf3inputTb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3out Tff7b72= Tb4b4b4[Tb4b4b4]Tb4b4b4;
Tff7b72let Te6edf3bitPos Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72const Te6edf3totalBits Tff7b72= Te6edf3inputTb4b4b4.Te6edf3length Tff7b72* T79c0ff8Tb4b4b4;
Tff7b72function Te6edf3readBitsTb4b4b4(Te6edf3nTb4b4b4)Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3bitPos Tff7b72+ Te6edf3n Tff7b72> Te6edf3totalBitsTb4b4b4) Tff7b72return Tff7b72-T79c0ff1Tb4b4b4;
Tff7b72let Te6edf3v Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72let Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< Te6edf3nTb4b4b4; Te6edf3iTff7b72++Tb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3byteIdx Tff7b72= Te6edf3bitPos Tff7b72>> T79c0ff3Tb4b4b4;
Tff7b72const Te6edf3bitInByte Tff7b72= T79c0ff7 Tff7b72- Tb4b4b4(Te6edf3bitPos Tff7b72& T79c0ff7Tb4b4b4)Tb4b4b4;
Te6edf3v Tff7b72= Tb4b4b4(Te6edf3v Tff7b72<< T79c0ff1Tb4b4b4) Tff7b72| Tb4b4b4(Tb4b4b4(Te6edf3inputTb4b4b4[Te6edf3byteIdxTb4b4b4] Tff7b72>> Te6edf3bitInByteTb4b4b4) Tff7b72& T79c0ff1Tb4b4b4)Tb4b4b4;
Te6edf3bitPosTff7b72++Tb4b4b4;
Tb4b4b4}
Tff7b72return Te6edf3vTb4b4b4;
Tb4b4b4}
Tff7b72while Tb4b4b4(Te6edf3bitPos Tff7b72< Te6edf3totalBitsTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3tag Tff7b72= Te6edf3readBitsTb4b4b4(T79c0ff1Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3tag Tff7b72< T79c0ff0Tb4b4b4) Tff7b72breakTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3tag Tff7b72=== T79c0ff1Tb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3b Tff7b72= Te6edf3readBitsTb4b4b4(T79c0ff8Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3b Tff7b72< T79c0ff0Tb4b4b4) Tff7b72breakTb4b4b4;
Te6edf3outTb4b4b4.Te6edf3pushTb4b4b4(Te6edf3bTb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72const Te6edf3offRaw Tff7b72= Te6edf3readBitsTb4b4b4(Te6edf3HS_WINDOW_BITSTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3offRaw Tff7b72< T79c0ff0Tb4b4b4) Tff7b72breakTb4b4b4;
Tff7b72const Te6edf3lenRaw Tff7b72= Te6edf3readBitsTb4b4b4(Te6edf3HS_LOOKAHEAD_BITSTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3lenRaw Tff7b72< T79c0ff0Tb4b4b4) Tff7b72breakTb4b4b4;
T8b949e// heatshrink encodes offset and length as (real-value - 1) on the
T8b949e// wire — see heatshrink_decoder.c HSDS_BACKREF_INDEX_LSB /
T8b949e// HSDS_BACKREF_COUNT_LSB states. Minimum match length is 2 (a
T8b949e// 1-byte match would cost more bits than a literal), so wire_length
T8b949e// ranges 1..(2^lookahead_bits - 1) → real_length 2..(2^lb).
Tff7b72const Te6edf3offset Tff7b72= Te6edf3offRaw Tff7b72+ T79c0ff1Tb4b4b4;
Tff7b72const Te6edf3length Tff7b72= Te6edf3lenRaw Tff7b72+ T79c0ff1Tb4b4b4;
T8b949e// The C encoder/decoder both pre-zero a (1<<HS_WINDOW_BITS) byte
T8b949e// sliding window (memset in heatshrink_{en,de}coder.c::reset), and
T8b949e// the encoder is allowed to emit backrefs that point into that
T8b949e// zero region — i.e., "before" any byte has actually been emitted.
T8b949e// Treat negative indices as that virtual zero source rather than
T8b949e// bailing; bailing silently truncates every stream that compresses
T8b949e// an early zero run (common for msgpack float64 metrics).
Tff7b72const Te6edf3start Tff7b72= Te6edf3outTb4b4b4.Te6edf3length Tff7b72- Te6edf3offsetTb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72let Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< Te6edf3lengthTb4b4b4; Te6edf3iTff7b72++Tb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3idx Tff7b72= Te6edf3start Tff7b72+ Te6edf3iTb4b4b4;
Te6edf3outTb4b4b4.Te6edf3pushTb4b4b4(Te6edf3idx Tff7b72< T79c0ff0 Tff7b72? T79c0ff0 Tff7b72: Te6edf3outTb4b4b4[Te6edf3idxTb4b4b4]Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72return Tff7b72new Tffa657Uint8ArrayTb4b4b4(Te6edf3outTb4b4b4)Tb4b4b4;
Tb4b4b4}

T8b949e// ===== Provisioning client =====
Tff7b72class Te6edf3ProvisioningClient Tb4b4b4{
Tff7b72constructorTb4b4b4(Te6edf3transportTb4b4b4)Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3t Tff7b72= Te6edf3transportTb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3seq Tff7b72= T79c0ff1Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3waiters Tff7b72= Tff7b72new Tffa657MapTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3onLog Tff7b72= Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{Tb4b4b4}Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3onStatusFrame Tff7b72= Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{Tb4b4b4}Tb4b4b4;
T8b949e// Fallthrough: any KISS opcode we don't recognise here is offered to the
T8b949e// LegacyClient (for rnodeconf-style CMD_FREQUENCY, CMD_BT_CTRL, etc).
Tff7b72thisTb4b4b4.Te6edf3onLegacyFrame Tff7b72= Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{Tb4b4b4}Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3decoder Tff7b72= Tff7b72new Te6edf3KissDecoderTb4b4b4(Tb4b4b4(Te6edf3cmdTb4b4b4, Te6edf3payloadTb4b4b4) Tb4b4b4=> Tff7b72thisTb4b4b4.Te6edf3_onFrameTb4b4b4(Te6edf3cmdTb4b4b4, Te6edf3payloadTb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3tTb4b4b4.Te6edf3onBytes Tff7b72= Tb4b4b4(Te6edf3bTb4b4b4) Tb4b4b4=> Tff7b72thisTb4b4b4.Te6edf3decoderTb4b4b4.Te6edf3feedTb4b4b4(Te6edf3bTb4b4b4)Tb4b4b4;
T8b949e// Whether to ask the server for compressed responses on bulky ops.
T8b949e// Picked up by duck-typing from the transport (LoRa-backed transports
T8b949e// set `compressionPreferred = true`). Local Serial / WebSocket leave
T8b949e// it false: bytes are cheap there and decompression adds latency.
Tff7b72thisTb4b4b4.Te6edf3compressionEnabled Tff7b72= Tff7b72!Tff7b72!Tb4b4b4(Te6edf3transport Tff7b72&& Te6edf3transportTb4b4b4.Te6edf3compressionPreferredTb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3_onFrameTb4b4b4(Te6edf3cmdTb4b4b4, Te6edf3payloadTb4b4b4)Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3cmd Tff7b72=== Te6edf3CMD_PROVISION_RSPTb4b4b4) Tff7b72thisTb4b4b4.Te6edf3_onResponseTb4b4b4(Te6edf3payloadTb4b4b4)Tb4b4b4;
Tff7b72else Tff7b72if Tb4b4b4(Te6edf3cmd Tff7b72=== Te6edf3CMD_LOGTb4b4b4) Tff7b72thisTb4b4b4.Te6edf3onLogTb4b4b4(Tff7b72new Te6edf3TextDecoderTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3decodeTb4b4b4(Te6edf3payloadTb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72else Tff7b72if Tb4b4b4(Te6edf3cmd Tff7b72>= Te6edf3STAT_CMD_RANGETb4b4b4[T79c0ff0Tb4b4b4] Tff7b72&& Te6edf3cmd Tff7b72<= Te6edf3STAT_CMD_RANGETb4b4b4[T79c0ff1Tb4b4b4]Tb4b4b4) Tff7b72thisTb4b4b4.Te6edf3onStatusFrameTb4b4b4(Te6edf3cmdTb4b4b4, Te6edf3payloadTb4b4b4)Tb4b4b4;
Tff7b72else Tff7b72thisTb4b4b4.Te6edf3onLegacyFrameTb4b4b4(Te6edf3cmdTb4b4b4, Te6edf3payloadTb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3_onResponseTb4b4b4(Te6edf3payloadTb4b4b4)Tb4b4b4{
Tff7b72let Te6edf3envTb4b4b4;
Tff7b72try Tb4b4b4{ Te6edf3env Tff7b72= Tff7b72new Te6edf3UnpackerTb4b4b4(Te6edf3payloadTb4b4b4)Tb4b4b4.Te6edf3nextTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Te6edf3consoleTb4b4b4.Te6edf3errorTb4b4b4(Ta5d6ff'msgpack decode failed:'Tb4b4b4, Te6edf3eTb4b4b4)Tb4b4b4; Tff7b72returnTb4b4b4; Tb4b4b4}
Tff7b72if Tb4b4b4(Tff7b72!Tffa657ArrayTb4b4b4.Te6edf3isArrayTb4b4b4(Te6edf3envTb4b4b4) Tff7b72|| Te6edf3envTb4b4b4.Te6edf3length Tff7b72< T79c0ff2Tb4b4b4) Tff7b72returnTb4b4b4;
Tff7b72const Te6edf3op Tff7b72= Tffa657NumberTb4b4b4(Te6edf3envTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3seq Tff7b72= Tffa657NumberTb4b4b4(Te6edf3envTb4b4b4[T79c0ff1Tb4b4b4]Tb4b4b4)Tb4b4b4;
Tff7b72let Te6edf3body Tff7b72= Te6edf3envTb4b4b4.Te6edf3length Tff7b72>= T79c0ff3 Tff7b72? Te6edf3envTb4b4b4[T79c0ff2Tb4b4b4] Tff7b72: Tff7b72nullTb4b4b4;
Tff7b72const Te6edf3w Tff7b72= Tff7b72thisTb4b4b4.Te6edf3waitersTb4b4b4.Te6edf3getTb4b4b4(Te6edf3seqTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3wTb4b4b4) Tff7b72returnTb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3waitersTb4b4b4.Tff7b72deleteTb4b4b4(Te6edf3seqTb4b4b4)Tb4b4b4;
Te6edf3clearTimeoutTb4b4b4(Te6edf3wTb4b4b4.Te6edf3timeoutIdTb4b4b4)Tb4b4b4;
T8b949e// Compressed-payload sentinel: a single-key map { CompressedPayload: <bin> }
T8b949e// whose value decompresses to the original MsgPack-encoded payload.
T8b949e// Transparent to the dispatch below — once decoded, body looks identical
T8b949e// to what an uncompressed response would have produced.
Tff7b72if Tb4b4b4(Te6edf3body Tff7b72instanceof Tffa657Map Tff7b72&& Te6edf3bodyTb4b4b4.Te6edf3size Tff7b72=== T79c0ff1 Tff7b72&& Te6edf3bodyTb4b4b4.Te6edf3hasTb4b4b4(Te6edf3WKTb4b4b4.Te6edf3CompressedPayloadTb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3bin Tff7b72= Te6edf3bodyTb4b4b4.Te6edf3getTb4b4b4(Te6edf3WKTb4b4b4.Te6edf3CompressedPayloadTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3bin Tff7b72instanceof Tffa657Uint8ArrayTb4b4b4) Tb4b4b4{
Tff7b72try Tb4b4b4{
Tff7b72const Te6edf3raw Tff7b72= Te6edf3heatshrinkDecodeTb4b4b4(Te6edf3binTb4b4b4)Tb4b4b4;
Te6edf3body Tff7b72= Tff7b72new Te6edf3UnpackerTb4b4b4(Te6edf3rawTb4b4b4)Tb4b4b4.Te6edf3nextTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{
Te6edf3consoleTb4b4b4.Te6edf3errorTb4b4b4(Ta5d6ff'compressed payload decode failed:'Tb4b4b4, Te6edf3eTb4b4b4)Tb4b4b4;
Te6edf3wTb4b4b4.Te6edf3rejectTb4b4b4(Tff7b72new Tf85149ErrorTb4b4b4(Ta5d6ff'failed to decompress response: ' Tff7b72+ Tb4b4b4(Te6edf3e Tff7b72&& Te6edf3eTb4b4b4.Te6edf3messageTb4b4b4)Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72returnTb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3op Tff7b72=== Te6edf3OPTb4b4b4.Tf85149ErrorTb4b4b4) Tb4b4b4{
T8b949e// Defensive against decoders that hand us a plain Object instead of a
T8b949e// Map for int-keyed msgpack maps. Some JS msgpack libs surface int keys
T8b949e// as Map entries, others coerce to string-keyed Object — handle both.
Tff7b72const Te6edf3getF Tff7b72= Tb4b4b4(Te6edf3keyTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3body Tff7b72instanceof Tffa657MapTb4b4b4) Tff7b72return Te6edf3bodyTb4b4b4.Te6edf3getTb4b4b4(Te6edf3keyTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3body Tff7b72&& Tff7b72typeof Te6edf3body Tff7b72=== Ta5d6ff'object'Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3key Tff7b72in Te6edf3bodyTb4b4b4) Tff7b72return Te6edf3bodyTb4b4b4[Te6edf3keyTb4b4b4]Tb4b4b4;
Tff7b72const Te6edf3skey Tff7b72= Tffa657StringTb4b4b4(Te6edf3keyTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3skey Tff7b72in Te6edf3bodyTb4b4b4) Tff7b72return Te6edf3bodyTb4b4b4[Te6edf3skeyTb4b4b4]Tb4b4b4;
Tb4b4b4}
Tff7b72return Tff7b72undefinedTb4b4b4;
Tb4b4b4}Tb4b4b4;
Tff7b72const Te6edf3msg Tff7b72= Te6edf3getFTb4b4b4(Te6edf3EKTb4b4b4.Te6edf3MessageTb4b4b4) Tff7b72|| Ta5d6ff'Provisioning error'Tb4b4b4;
Tff7b72const Te6edf3code Tff7b72= Te6edf3getFTb4b4b4(Te6edf3EKTb4b4b4.Te6edf3CodeTb4b4b4) Tff7b72?? T79c0ff99Tb4b4b4;
Tff7b72const Te6edf3codeName Tff7b72= Te6edf3ERR_NAMESTb4b4b4[Te6edf3codeTb4b4b4] Tff7b72|| Ta5d6ff'Unknown'Tb4b4b4;
Tff7b72const Te6edf3err Tff7b72= Tff7b72new Tf85149ErrorTb4b4b4(Ta5d6ff`Tffd700${Te6edf3msgTffd700}Ta5d6ff (code Tffd700${Te6edf3codeTffd700}Ta5d6ff Tffd700${Te6edf3codeNameTffd700}Ta5d6ff)Ta5d6ff`Tb4b4b4)Tb4b4b4;
Te6edf3errTb4b4b4.Te6edf3code Tff7b72= Te6edf3codeTb4b4b4;
Te6edf3errTb4b4b4.Te6edf3codeName Tff7b72= Te6edf3codeNameTb4b4b4;
Te6edf3errTb4b4b4.Te6edf3message_raw Tff7b72= Te6edf3msgTb4b4b4;
Te6edf3errTb4b4b4.Te6edf3ns Tff7b72= Te6edf3getFTb4b4b4(Te6edf3EKTb4b4b4.Te6edf3NamespaceTb4b4b4)Tb4b4b4;
Te6edf3errTb4b4b4.Te6edf3field Tff7b72= Te6edf3getFTb4b4b4(Te6edf3EKTb4b4b4.Te6edf3FieldTb4b4b4)Tb4b4b4;
Te6edf3wTb4b4b4.Te6edf3rejectTb4b4b4(Te6edf3errTb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3wTb4b4b4.Te6edf3resolveTb4b4b4(Tb4b4b4{ Te6edf3opTb4b4b4, Te6edf3body Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72async Te6edf3_requestTb4b4b4(Te6edf3opIdTb4b4b4, Te6edf3packPayloadTb4b4b4, Te6edf3timeoutMsTb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3seq Tff7b72= Tff7b72thisTb4b4b4.Te6edf3seqTff7b72++Tb4b4b4;
Tff7b72const Te6edf3p Tff7b72= Tff7b72new Te6edf3PackerTb4b4b4(Tb4b4b4)Tb4b4b4;
T8b949e// Compression negotiation: for ops whose payload either is currently nil
T8b949e// (no map) or already a map of "options" with known keys, optionally
T8b949e// inject the ReqCompress flag. SetState/Commit/Discard are excluded
T8b949e// because their payload shapes (nsId-keyed map / array of nsIds) would
T8b949e// collide with the flag's uint16 key and break the server-side parser.
Tff7b72const Te6edf3wantsCompress Tff7b72= Tff7b72thisTb4b4b4.Te6edf3compressionEnabled Tff7b72&& Te6edf3COMPRESSIBLE_OPSTb4b4b4.Te6edf3hasTb4b4b4(Te6edf3opIdTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3has Tff7b72= Tff7b72!Tff7b72!Te6edf3packPayload Tff7b72|| Te6edf3wantsCompressTb4b4b4;
Te6edf3pTb4b4b4.Te6edf3arrTb4b4b4(Te6edf3has Tff7b72? T79c0ff3 Tff7b72: T79c0ff2Tb4b4b4)Tb4b4b4;
Te6edf3pTb4b4b4.Tff7b72intTb4b4b4(Te6edf3opIdTb4b4b4)Tb4b4b4;
Te6edf3pTb4b4b4.Tff7b72intTb4b4b4(Te6edf3seqTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3packPayloadTb4b4b4) Tb4b4b4{
T8b949e// Caller-driven payload. Pass wantsCompress through ctx so the
T8b949e// caller (e.g. getState) can fold ReqCompress into its own map.
Te6edf3packPayloadTb4b4b4(Te6edf3pTb4b4b4, Tb4b4b4{ Te6edf3wantsCompress Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3wantsCompressTb4b4b4) Tb4b4b4{
T8b949e// No caller payload — emit a single-entry map carrying just the flag.
Te6edf3pTb4b4b4.Te6edf3mapTb4b4b4(T79c0ff1Tb4b4b4)Tb4b4b4;
Te6edf3pTb4b4b4.Tff7b72intTb4b4b4(Te6edf3WKTb4b4b4.Te6edf3ReqCompressTb4b4b4)Tb4b4b4;
Te6edf3pTb4b4b4.Te6edf3boolTb4b4b4(Tff7b72trueTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72const Te6edf3frame Tff7b72= Te6edf3kissEncodeTb4b4b4(Te6edf3CMD_PROVISION_REQTb4b4b4, Te6edf3pTb4b4b4.Te6edf3resultTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
T8b949e// Per-call timeout wins; otherwise the transport's advertised default
T8b949e// (RnsTransport publishes a longer one because LoRa Resource transfers
T8b949e// can take 30+ seconds); final fallback is the snappy 5s default suited
T8b949e// to Serial / BLE / WebSocket.
Tff7b72const Te6edf3transportDefault Tff7b72= Tb4b4b4(Tff7b72thisTb4b4b4.Te6edf3t Tff7b72&& Tff7b72typeof Tff7b72thisTb4b4b4.Te6edf3tTb4b4b4.Te6edf3defaultRequestTimeoutMs Tff7b72=== Ta5d6ff'number'Tb4b4b4) Tff7b72? Tff7b72thisTb4b4b4.Te6edf3tTb4b4b4.Te6edf3defaultRequestTimeoutMs Tff7b72: Tff7b72nullTb4b4b4;
Tff7b72const Te6edf3timeout Tff7b72= Tb4b4b4(Te6edf3timeoutMs Tff7b72!= Tff7b72nullTb4b4b4) Tff7b72? Te6edf3timeoutMs Tff7b72: Tb4b4b4(Te6edf3transportDefault Tff7b72!= Tff7b72null Tff7b72? Te6edf3transportDefault Tff7b72: T79c0ff5000Tb4b4b4)Tb4b4b4;
Tff7b72return Tff7b72new Tffa657PromiseTb4b4b4(Tb4b4b4(Te6edf3resolveTb4b4b4, Te6edf3rejectTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3timeoutId Tff7b72= Te6edf3setTimeoutTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3waitersTb4b4b4.Tff7b72deleteTb4b4b4(Te6edf3seqTb4b4b4)Tb4b4b4;
Te6edf3rejectTb4b4b4(Tff7b72new Tf85149ErrorTb4b4b4(Ta5d6ff'Provisioning request timed out (op 'Tff7b72+Te6edf3opIdTff7b72+Ta5d6ff')'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4, Te6edf3timeoutTb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3waitersTb4b4b4.Te6edf3setTb4b4b4(Te6edf3seqTb4b4b4, Tb4b4b4{ Te6edf3resolveTb4b4b4, Te6edf3rejectTb4b4b4, Te6edf3timeoutId Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tffa657PromiseTb4b4b4.Te6edf3resolveTb4b4b4(Tff7b72thisTb4b4b4.Te6edf3tTb4b4b4.Te6edf3sendTb4b4b4(Te6edf3frameTb4b4b4)Tb4b4b4)Tb4b4b4.Tff7b72catchTb4b4b4(Te6edf3rejectTb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}
T8b949e// timeoutMs lets callers override the default 5s — used by the reconnect
T8b949e// probe loop, which wants a short timeout so it can retry rapidly while the
T8b949e// firmware finishes booting.
Tff7b72async Te6edf3getInfoTb4b4b4(Te6edf3timeoutMsTb4b4b4)Tb4b4b4{
Tff7b72const Tb4b4b4{ Te6edf3body Tb4b4b4} Tff7b72= Tff7b72await Tff7b72thisTb4b4b4.Te6edf3_requestTb4b4b4(Te6edf3OPTb4b4b4.Te6edf3GetInfoTb4b4b4, Tff7b72nullTb4b4b4, Te6edf3timeoutMsTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3m Tff7b72= Te6edf3body Tff7b72instanceof Tffa657Map Tff7b72? Te6edf3body Tff7b72: Tff7b72new Tffa657MapTb4b4b4(Tb4b4b4)Tb4b4b4;
T8b949e// schemaHash is a uint32 CRC32 over the GetSchema response bytes. Older
T8b949e// firmware that doesn't include it returns undefined here, which the
T8b949e// schema cache layer treats as "uncacheable" and falls back to fetch.
Tff7b72return Tb4b4b4{
Te6edf3firmwareVersionTff7b72: Te6edf3mTb4b4b4.Te6edf3getTb4b4b4(Te6edf3IKTb4b4b4.Te6edf3FirmwareVersionTb4b4b4)Tb4b4b4,
Te6edf3schemaVersionTff7b72: Te6edf3mTb4b4b4.Te6edf3getTb4b4b4(Te6edf3IKTb4b4b4.Te6edf3SchemaVersionTb4b4b4)Tb4b4b4,
Te6edf3needsRebootTff7b72: Tff7b72!Tff7b72!Te6edf3mTb4b4b4.Te6edf3getTb4b4b4(Te6edf3IKTb4b4b4.Te6edf3NeedsRebootTb4b4b4)Tb4b4b4,
Te6edf3schemaHashTff7b72: Te6edf3mTb4b4b4.Te6edf3getTb4b4b4(Te6edf3IKTb4b4b4.Te6edf3SchemaHashTb4b4b4)Tb4b4b4,
Tb4b4b4}Tb4b4b4;
Tb4b4b4}
Tff7b72async Te6edf3getSchemaTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72const Tb4b4b4{ Te6edf3body Tb4b4b4} Tff7b72= Tff7b72await Tff7b72thisTb4b4b4.Te6edf3_requestTb4b4b4(Te6edf3OPTb4b4b4.Te6edf3GetSchemaTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3namespaces Tff7b72= Tb4b4b4[Tb4b4b4]Tb4b4b4;
Tff7b72if Tb4b4b4(Tffa657ArrayTb4b4b4.Te6edf3isArrayTb4b4b4(Te6edf3bodyTb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3nsEntry Tff7b72of Te6edf3bodyTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Tffa657ArrayTb4b4b4.Te6edf3isArrayTb4b4b4(Te6edf3nsEntryTb4b4b4) Tff7b72|| Te6edf3nsEntryTb4b4b4.Te6edf3length Tff7b72< T79c0ff3Tb4b4b4) Tff7b72continueTb4b4b4;
T8b949e// Schema v2: namespace entry is [id, name, parent_id, fields]. v1 was
T8b949e// [id, name, fields]. Length distinguishes them; parent_id == 0 means
T8b949e// root (no parent) in v2.
Tff7b72const Te6edf3v2 Tff7b72= Te6edf3nsEntryTb4b4b4.Te6edf3length Tff7b72>= T79c0ff4Tb4b4b4;
Tff7b72const Te6edf3parentId Tff7b72= Te6edf3v2 Tff7b72? Tffa657NumberTb4b4b4(Te6edf3nsEntryTb4b4b4[T79c0ff2Tb4b4b4] Tff7b72|| T79c0ff0Tb4b4b4) Tff7b72: T79c0ff0Tb4b4b4;
Tff7b72const Te6edf3fieldsRaw Tff7b72= Te6edf3v2 Tff7b72? Te6edf3nsEntryTb4b4b4[T79c0ff3Tb4b4b4] Tff7b72: Te6edf3nsEntryTb4b4b4[T79c0ff2Tb4b4b4]Tb4b4b4;
Tff7b72const Te6edf3fields Tff7b72= Tb4b4b4[Tb4b4b4]Tb4b4b4;
Tff7b72if Tb4b4b4(Tffa657ArrayTb4b4b4.Te6edf3isArrayTb4b4b4(Te6edf3fieldsRawTb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3fEntry Tff7b72of Te6edf3fieldsRawTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Tb4b4b4(Te6edf3fEntry Tff7b72instanceof Tffa657MapTb4b4b4)Tb4b4b4) Tff7b72continueTb4b4b4;
Te6edf3fieldsTb4b4b4.Te6edf3pushTb4b4b4(Tb4b4b4{
Te6edf3idTff7b72: Tffa657NumberTb4b4b4(Te6edf3fEntryTb4b4b4.Te6edf3getTb4b4b4(Te6edf3FKTb4b4b4.Te6edf3IdTb4b4b4)Tb4b4b4)Tb4b4b4,
Te6edf3nameTff7b72: Te6edf3fEntryTb4b4b4.Te6edf3getTb4b4b4(Te6edf3FKTb4b4b4.Te6edf3NameTb4b4b4)Tb4b4b4,
Te6edf3typeTff7b72: Tffa657NumberTb4b4b4(Te6edf3fEntryTb4b4b4.Te6edf3getTb4b4b4(Te6edf3FKTb4b4b4.Te6edf3TypeTb4b4b4)Tb4b4b4)Tb4b4b4,
Te6edf3flagsTff7b72: Tffa657NumberTb4b4b4(Te6edf3fEntryTb4b4b4.Te6edf3getTb4b4b4(Te6edf3FKTb4b4b4.Te6edf3FlagsTb4b4b4) Tff7b72|| T79c0ff0Tb4b4b4)Tb4b4b4,
Te6edf3minITff7b72: Te6edf3fEntryTb4b4b4.Te6edf3getTb4b4b4(Te6edf3FKTb4b4b4.Te6edf3MinITb4b4b4)Tb4b4b4, Te6edf3maxITff7b72: Te6edf3fEntryTb4b4b4.Te6edf3getTb4b4b4(Te6edf3FKTb4b4b4.Te6edf3MaxITb4b4b4)Tb4b4b4,
Te6edf3minFTff7b72: Te6edf3fEntryTb4b4b4.Te6edf3getTb4b4b4(Te6edf3FKTb4b4b4.Te6edf3MinFTb4b4b4)Tb4b4b4, Te6edf3maxFTff7b72: Te6edf3fEntryTb4b4b4.Te6edf3getTb4b4b4(Te6edf3FKTb4b4b4.Te6edf3MaxFTb4b4b4)Tb4b4b4,
Te6edf3maxLenTff7b72: Te6edf3fEntryTb4b4b4.Te6edf3getTb4b4b4(Te6edf3FKTb4b4b4.Te6edf3MaxLenTb4b4b4)Tb4b4b4,
Te6edf3enumValuesTff7b72: Te6edf3fEntryTb4b4b4.Te6edf3getTb4b4b4(Te6edf3FKTb4b4b4.Te6edf3EnumValuesTb4b4b4)Tb4b4b4, Te6edf3enumLabelsTff7b72: Te6edf3fEntryTb4b4b4.Te6edf3getTb4b4b4(Te6edf3FKTb4b4b4.Te6edf3EnumLabelsTb4b4b4)Tb4b4b4,
T8b949e// BytesList constraints (Type::BytesList only):
T8b949e// elementSize = required exact byte length per entry (0 = variable)
T8b949e// maxCount = max number of entries (0 = unlimited)
Te6edf3elementSizeTff7b72: Te6edf3fEntryTb4b4b4.Te6edf3getTb4b4b4(Te6edf3FKTb4b4b4.Te6edf3ElementSizeTb4b4b4)Tb4b4b4,
Te6edf3maxCountTff7b72: Te6edf3fEntryTb4b4b4.Te6edf3getTb4b4b4(Te6edf3FKTb4b4b4.Te6edf3MaxCountTb4b4b4)Tb4b4b4,
Tff7b72defaultTff7b72: Te6edf3fEntryTb4b4b4.Te6edf3getTb4b4b4(Te6edf3FKTb4b4b4.Te6edf3DefaultTb4b4b4)Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Te6edf3namespacesTb4b4b4.Te6edf3pushTb4b4b4(Tb4b4b4{ Te6edf3idTff7b72: Tffa657NumberTb4b4b4(Te6edf3nsEntryTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4)Tb4b4b4, Te6edf3nameTff7b72: Tffa657StringTb4b4b4(Te6edf3nsEntryTb4b4b4[T79c0ff1Tb4b4b4]Tb4b4b4)Tb4b4b4, Te6edf3parentIdTb4b4b4, Te6edf3fields Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72return Tb4b4b4{ Te6edf3namespaces Tb4b4b4}Tb4b4b4;
Tb4b4b4}
T8b949e// Resolve the device's schema, preferring (1) a build-time bundled schema
T8b949e// whose hash matches the device, then (2) a localStorage cache entry keyed
T8b949e// by (schemaVersion, schemaHash), then (3) a network GetSchema fetch. The
T8b949e// hash is the CRC32 the firmware computes over the GetSchema response
T8b949e// bytes at boot and reports in GetInfo; identical hashes imply identical
T8b949e// schemas, so no per-device key is needed.
T8b949e//
T8b949e// Firmware that predates SchemaHash returns info.schemaHash === undefined,
T8b949e// in which case we bypass cache and bundle and just fetch as before.
Tff7b72async Te6edf3resolveSchemaTb4b4b4(Te6edf3infoTb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3hash Tff7b72= Te6edf3info Tff7b72&& Te6edf3infoTb4b4b4.Te6edf3schemaHashTb4b4b4;
Tff7b72const Te6edf3ver Tff7b72= Te6edf3info Tff7b72&& Te6edf3infoTb4b4b4.Te6edf3schemaVersionTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3hash Tff7b72== Tff7b72null Tff7b72|| Te6edf3ver Tff7b72== Tff7b72nullTb4b4b4) Tff7b72return Tff7b72await Tff7b72thisTb4b4b4.Te6edf3getSchemaTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3hashHex Tff7b72= Tb4b4b4(Tffa657NumberTb4b4b4(Te6edf3hashTb4b4b4) Tff7b72>>> T79c0ff0Tb4b4b4)Tb4b4b4.Te6edf3toStringTb4b4b4(T79c0ff16Tb4b4b4)Tb4b4b4.Te6edf3padStartTb4b4b4(T79c0ff8Tb4b4b4, Ta5d6ff'0'Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3cacheKey Tff7b72= Ta5d6ff`Ta5d6ffmrf_schema_vTffd700${Tffa657NumberTb4b4b4(Te6edf3verTb4b4b4)Tffd700}Ta5d6ff_Tffd700${Te6edf3hashHexTffd700}Ta5d6ff`Tb4b4b4;
T8b949e// 1) Bundled (zero network).
Tff7b72if Tb4b4b4(Te6edf3BUNDLED_SCHEMA Tff7b72&&
Tffa657NumberTb4b4b4(Te6edf3BUNDLED_SCHEMATb4b4b4.Te6edf3versionTb4b4b4) Tff7b72=== Tffa657NumberTb4b4b4(Te6edf3verTb4b4b4) Tff7b72&&
Tb4b4b4(Tffa657NumberTb4b4b4(Te6edf3BUNDLED_SCHEMATb4b4b4.Te6edf3hashTb4b4b4) Tff7b72>>> T79c0ff0Tb4b4b4) Tff7b72=== Tb4b4b4(Tffa657NumberTb4b4b4(Te6edf3hashTb4b4b4) Tff7b72>>> T79c0ff0Tb4b4b4) Tff7b72&&
Tff7b72typeof Te6edf3BUNDLED_SCHEMATb4b4b4.Te6edf3schemaJson Tff7b72=== Ta5d6ff'string'Tb4b4b4) Tb4b4b4{
Tff7b72try Tb4b4b4{ Tff7b72return Te6edf3_schemaDeserializeTb4b4b4(Te6edf3BUNDLED_SCHEMATb4b4b4.Te6edf3schemaJsonTb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4}
Tb4b4b4}
T8b949e// 2) localStorage cache.
Tff7b72try Tb4b4b4{
Tff7b72const Te6edf3raw Tff7b72= Tffa657windowTb4b4b4.Te6edf3localStorage Tff7b72&& Te6edf3localStorageTb4b4b4.Te6edf3getItemTb4b4b4(Te6edf3cacheKeyTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3rawTb4b4b4) Tff7b72return Te6edf3_schemaDeserializeTb4b4b4(Te6edf3rawTb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4}
T8b949e// 3) Fetch + persist.
Tff7b72const Te6edf3schema Tff7b72= Tff7b72await Tff7b72thisTb4b4b4.Te6edf3getSchemaTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72try Tb4b4b4{
Tff7b72if Tb4b4b4(Tffa657windowTb4b4b4.Te6edf3localStorageTb4b4b4) Tb4b4b4{
Te6edf3_schemaCachePruneTb4b4b4(Te6edf3cacheKeyTb4b4b4)Tb4b4b4;
Te6edf3localStorageTb4b4b4.Te6edf3setItemTb4b4b4(Te6edf3cacheKeyTb4b4b4, Te6edf3_schemaSerializeTb4b4b4(Te6edf3schemaTb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{ T8b949e/* quota/disabled — non-fatal */ Tb4b4b4}
Tff7b72return Te6edf3schemaTb4b4b4;
Tb4b4b4}
Tff7b72async Te6edf3getStateTb4b4b4(Te6edf3nsIdsTb4b4b4, Te6edf3pendingTb4b4b4)Tb4b4b4{
Tff7b72const Tb4b4b4{ Te6edf3body Tb4b4b4} Tff7b72= Tff7b72await Tff7b72thisTb4b4b4.Te6edf3_requestTb4b4b4(Te6edf3OPTb4b4b4.Te6edf3GetStateTb4b4b4, Tb4b4b4(Te6edf3pTb4b4b4, Te6edf3ctxTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3hasFilter Tff7b72= Tffa657ArrayTb4b4b4.Te6edf3isArrayTb4b4b4(Te6edf3nsIdsTb4b4b4) Tff7b72&& Te6edf3nsIdsTb4b4b4.Te6edf3length Tff7b72> T79c0ff0Tb4b4b4;
Tff7b72const Te6edf3compress Tff7b72= Tff7b72!Tff7b72!Tb4b4b4(Te6edf3ctx Tff7b72&& Te6edf3ctxTb4b4b4.Te6edf3wantsCompressTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3entries Tff7b72= Tb4b4b4(Te6edf3hasFilter Tff7b72? T79c0ff1 Tff7b72: T79c0ff0Tb4b4b4) Tff7b72+ Tb4b4b4(Te6edf3pending Tff7b72? T79c0ff1 Tff7b72: T79c0ff0Tb4b4b4) Tff7b72+ Tb4b4b4(Te6edf3compress Tff7b72? T79c0ff1 Tff7b72: T79c0ff0Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3entries Tff7b72=== T79c0ff0Tb4b4b4) Tb4b4b4{ Te6edf3pTb4b4b4.Te6edf3nilTb4b4b4(Tb4b4b4)Tb4b4b4; Tff7b72returnTb4b4b4; Tb4b4b4}
Te6edf3pTb4b4b4.Te6edf3mapTb4b4b4(Te6edf3entriesTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3hasFilterTb4b4b4) Tb4b4b4{ Te6edf3pTb4b4b4.Tff7b72intTb4b4b4(Te6edf3GKTb4b4b4.Te6edf3NamespaceFilterTb4b4b4)Tb4b4b4; Te6edf3pTb4b4b4.Te6edf3arrTb4b4b4(Te6edf3nsIdsTb4b4b4.Te6edf3lengthTb4b4b4)Tb4b4b4; Tff7b72for Tb4b4b4(Tff7b72const Te6edf3n Tff7b72of Te6edf3nsIdsTb4b4b4) Te6edf3pTb4b4b4.Tff7b72intTb4b4b4(Te6edf3nTb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3pendingTb4b4b4) Tb4b4b4{ Te6edf3pTb4b4b4.Tff7b72intTb4b4b4(Te6edf3GKTb4b4b4.Te6edf3PendingTb4b4b4)Tb4b4b4; Te6edf3pTb4b4b4.Te6edf3boolTb4b4b4(Tff7b72trueTb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3compressTb4b4b4) Tb4b4b4{ Te6edf3pTb4b4b4.Tff7b72intTb4b4b4(Te6edf3WKTb4b4b4.Te6edf3ReqCompressTb4b4b4)Tb4b4b4; Te6edf3pTb4b4b4.Te6edf3boolTb4b4b4(Tff7b72trueTb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3out Tff7b72= Tb4b4b4{Tb4b4b4}Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3body Tff7b72instanceof Tffa657MapTb4b4b4) Tb4b4b4{
Tff7b72for Tb4b4b4(Tff7b72const Tb4b4b4[Te6edf3nsIdTb4b4b4, Te6edf3fieldsTb4b4b4] Tff7b72of Te6edf3bodyTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3f Tff7b72= Tb4b4b4{Tb4b4b4}Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3fields Tff7b72instanceof Tffa657MapTb4b4b4) Tff7b72for Tb4b4b4(Tff7b72const Tb4b4b4[Te6edf3fidTb4b4b4, Te6edf3vTb4b4b4] Tff7b72of Te6edf3fieldsTb4b4b4) Te6edf3fTb4b4b4[Tffa657NumberTb4b4b4(Te6edf3fidTb4b4b4)Tb4b4b4] Tff7b72= Te6edf3vTb4b4b4;
Te6edf3outTb4b4b4[Tffa657NumberTb4b4b4(Te6edf3nsIdTb4b4b4)Tb4b4b4] Tff7b72= Te6edf3fTb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72return Te6edf3outTb4b4b4;
Tb4b4b4}
Tff7b72async Te6edf3setStateTb4b4b4(Te6edf3stateMapTb4b4b4)Tb4b4b4{
Tff7b72const Tb4b4b4{ Te6edf3body Tb4b4b4} Tff7b72= Tff7b72await Tff7b72thisTb4b4b4.Te6edf3_requestTb4b4b4(Te6edf3OPTb4b4b4.Te6edf3SetStateTb4b4b4, Tb4b4b4(Te6edf3pTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3nsIds Tff7b72= Tffa657ObjectTb4b4b4.Te6edf3keysTb4b4b4(Te6edf3stateMapTb4b4b4)Tb4b4b4.Te6edf3mapTb4b4b4(Tffa657NumberTb4b4b4)Tb4b4b4;
Te6edf3pTb4b4b4.Te6edf3mapTb4b4b4(Te6edf3nsIdsTb4b4b4.Te6edf3lengthTb4b4b4)Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3nsId Tff7b72of Te6edf3nsIdsTb4b4b4) Tb4b4b4{
Te6edf3pTb4b4b4.Tff7b72intTb4b4b4(Te6edf3nsIdTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3fields Tff7b72= Te6edf3stateMapTb4b4b4[Te6edf3nsIdTb4b4b4]Tb4b4b4;
Tff7b72const Te6edf3fids Tff7b72= Tffa657ObjectTb4b4b4.Te6edf3keysTb4b4b4(Te6edf3fieldsTb4b4b4)Tb4b4b4.Te6edf3mapTb4b4b4(Tffa657NumberTb4b4b4)Tb4b4b4;
Te6edf3pTb4b4b4.Te6edf3mapTb4b4b4(Te6edf3fidsTb4b4b4.Te6edf3lengthTb4b4b4)Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3fid Tff7b72of Te6edf3fidsTb4b4b4) Tb4b4b4{ Te6edf3pTb4b4b4.Tff7b72intTb4b4b4(Te6edf3fidTb4b4b4)Tb4b4b4; Te6edf3packTypedValueTb4b4b4(Te6edf3pTb4b4b4, Te6edf3fieldsTb4b4b4[Te6edf3fidTb4b4b4]Tb4b4b4.Te6edf3typeTb4b4b4, Te6edf3fieldsTb4b4b4[Te6edf3fidTb4b4b4]Tb4b4b4.Te6edf3valueTb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4}
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3m Tff7b72= Te6edf3body Tff7b72instanceof Tffa657Map Tff7b72? Te6edf3body Tff7b72: Tff7b72new Tffa657MapTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3errs Tff7b72= Te6edf3mTb4b4b4.Te6edf3getTb4b4b4(Te6edf3SKTb4b4b4.Te6edf3FieldErrorsTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3fieldErrors Tff7b72= Tffa657ArrayTb4b4b4.Te6edf3isArrayTb4b4b4(Te6edf3errsTb4b4b4) Tff7b72? Te6edf3errsTb4b4b4.Te6edf3mapTb4b4b4(Te6edf3e Tb4b4b4=> Tb4b4b4(Tb4b4b4{
Te6edf3nsTff7b72: Tffa657NumberTb4b4b4(Te6edf3eTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4)Tb4b4b4, Te6edf3fieldTff7b72: Tffa657NumberTb4b4b4(Te6edf3eTb4b4b4[T79c0ff1Tb4b4b4]Tb4b4b4)Tb4b4b4, Te6edf3codeTff7b72: Tffa657NumberTb4b4b4(Te6edf3eTb4b4b4[T79c0ff2Tb4b4b4]Tb4b4b4)Tb4b4b4, Te6edf3codeNameTff7b72: Te6edf3ERR_NAMESTb4b4b4[Tffa657NumberTb4b4b4(Te6edf3eTb4b4b4[T79c0ff2Tb4b4b4]Tb4b4b4)Tb4b4b4] Tff7b72|| Ta5d6ff'Unknown'Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4) Tff7b72: Tb4b4b4[Tb4b4b4]Tb4b4b4;
Tff7b72return Tb4b4b4{ Te6edf3appliedTff7b72: Tffa657NumberTb4b4b4(Te6edf3mTb4b4b4.Te6edf3getTb4b4b4(Te6edf3SKTb4b4b4.Te6edf3AppliedTb4b4b4) Tff7b72|| T79c0ff0Tb4b4b4)Tb4b4b4, Te6edf3draftHasRebootTff7b72: Tff7b72!Tff7b72!Te6edf3mTb4b4b4.Te6edf3getTb4b4b4(Te6edf3SKTb4b4b4.Te6edf3DraftHasRebootTb4b4b4)Tb4b4b4, Te6edf3fieldErrors Tb4b4b4}Tb4b4b4;
Tb4b4b4}
Tff7b72async Te6edf3commitTb4b4b4(Te6edf3nsIdsTb4b4b4)Tb4b4b4{
Tff7b72const Tb4b4b4{ Te6edf3body Tb4b4b4} Tff7b72= Tff7b72await Tff7b72thisTb4b4b4.Te6edf3_requestTb4b4b4(Te6edf3OPTb4b4b4.Te6edf3CommitTb4b4b4, Tb4b4b4(Te6edf3pTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72if Tb4b4b4(Tffa657ArrayTb4b4b4.Te6edf3isArrayTb4b4b4(Te6edf3nsIdsTb4b4b4) Tff7b72&& Te6edf3nsIdsTb4b4b4.Te6edf3length Tff7b72> T79c0ff0Tb4b4b4) Tb4b4b4{ Te6edf3pTb4b4b4.Te6edf3arrTb4b4b4(Te6edf3nsIdsTb4b4b4.Te6edf3lengthTb4b4b4)Tb4b4b4; Tff7b72for Tb4b4b4(Tff7b72const Te6edf3n Tff7b72of Te6edf3nsIdsTb4b4b4) Te6edf3pTb4b4b4.Tff7b72intTb4b4b4(Te6edf3nTb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72else Te6edf3pTb4b4b4.Te6edf3nilTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3m Tff7b72= Te6edf3body Tff7b72instanceof Tffa657Map Tff7b72? Te6edf3body Tff7b72: Tff7b72new Tffa657MapTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72return Tb4b4b4{ Te6edf3appliedTff7b72: Tffa657NumberTb4b4b4(Te6edf3mTb4b4b4.Te6edf3getTb4b4b4(Te6edf3CKTb4b4b4.Te6edf3AppliedTb4b4b4) Tff7b72|| T79c0ff0Tb4b4b4)Tb4b4b4, Te6edf3needsRebootTff7b72: Tff7b72!Tff7b72!Te6edf3mTb4b4b4.Te6edf3getTb4b4b4(Te6edf3CKTb4b4b4.Te6edf3NeedsRebootTb4b4b4) Tb4b4b4}Tb4b4b4;
Tb4b4b4}
Tff7b72async Te6edf3discardTb4b4b4(Te6edf3nsIdsTb4b4b4)Tb4b4b4{
Tff7b72const Tb4b4b4{ Te6edf3body Tb4b4b4} Tff7b72= Tff7b72await Tff7b72thisTb4b4b4.Te6edf3_requestTb4b4b4(Te6edf3OPTb4b4b4.Te6edf3DiscardTb4b4b4, Tb4b4b4(Te6edf3pTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72if Tb4b4b4(Tffa657ArrayTb4b4b4.Te6edf3isArrayTb4b4b4(Te6edf3nsIdsTb4b4b4) Tff7b72&& Te6edf3nsIdsTb4b4b4.Te6edf3length Tff7b72> T79c0ff0Tb4b4b4) Tb4b4b4{ Te6edf3pTb4b4b4.Te6edf3arrTb4b4b4(Te6edf3nsIdsTb4b4b4.Te6edf3lengthTb4b4b4)Tb4b4b4; Tff7b72for Tb4b4b4(Tff7b72const Te6edf3n Tff7b72of Te6edf3nsIdsTb4b4b4) Te6edf3pTb4b4b4.Tff7b72intTb4b4b4(Te6edf3nTb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72else Te6edf3pTb4b4b4.Te6edf3nilTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3m Tff7b72= Te6edf3body Tff7b72instanceof Tffa657Map Tff7b72? Te6edf3body Tff7b72: Tff7b72new Tffa657MapTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72return Tb4b4b4{ Te6edf3appliedTff7b72: Tffa657NumberTb4b4b4(Te6edf3mTb4b4b4.Te6edf3getTb4b4b4(Te6edf3CKTb4b4b4.Te6edf3AppliedTb4b4b4) Tff7b72|| T79c0ff0Tb4b4b4) Tb4b4b4}Tb4b4b4;
Tb4b4b4}
Tff7b72async Te6edf3factoryResetTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72const Tb4b4b4{ Te6edf3body Tb4b4b4} Tff7b72= Tff7b72await Tff7b72thisTb4b4b4.Te6edf3_requestTb4b4b4(Te6edf3OPTb4b4b4.Te6edf3FactoryResetTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3m Tff7b72= Te6edf3body Tff7b72instanceof Tffa657Map Tff7b72? Te6edf3body Tff7b72: Tff7b72new Tffa657MapTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72return Tb4b4b4{ Te6edf3needsRebootTff7b72: Tff7b72!Tff7b72!Te6edf3mTb4b4b4.Te6edf3getTb4b4b4(Te6edf3CKTb4b4b4.Te6edf3NeedsRebootTb4b4b4) Tb4b4b4}Tb4b4b4;
Tb4b4b4}
T8b949e// First-class Provisioning reboot — the library sends an Ack before
T8b949e// invoking the registered reboot callback, so a healthy device responds.
T8b949e// The Ack can still race with the actual reset (especially over slow RNS
T8b949e// links), so we use a short per-call timeout and treat *timeout* as
T8b949e// success: the request was emitted, the device almost certainly acted on
T8b949e// it. The only hard failure we surface is UnknownOp (code 2) — a device
T8b949e// too old to know about OP.Reboot — so callers can fall back cleanly to
T8b949e// the legacy KISS reset path.
Tff7b72async Te6edf3requestRebootTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72try Tb4b4b4{
Tff7b72await Tff7b72thisTb4b4b4.Te6edf3_requestTb4b4b4(Te6edf3OPTb4b4b4.Te6edf3RebootTb4b4b4, Tff7b72nullTb4b4b4, T79c0ff3000Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3e Tff7b72&& Tffa657NumberTb4b4b4(Te6edf3eTb4b4b4.Te6edf3codeTb4b4b4) Tff7b72=== T79c0ff2Tb4b4b4) Tff7b72throw Te6edf3eTb4b4b4; T8b949e// UnknownOp — propagate
T8b949e// timeout / connection-lost / link teardown mid-request — assume
T8b949e// the reboot fired and let the caller proceed with teardown.
Tb4b4b4}
Tb4b4b4}
T8b949e// Fire-and-forget reset via the legacy RNode KISS reset frame
T8b949e// (FEND CMD_RESET CMD_RESET_BYTE FEND). The device reboots immediately,
T8b949e// so there is no response — we just send the bytes. Used as the fallback
T8b949e// for legacy RNodes that don't implement OP.Reboot.
Tff7b72async Te6edf3rebootTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72await Tff7b72thisTb4b4b4.Te6edf3tTb4b4b4.Te6edf3sendTb4b4b4(Te6edf3kissEncodeTb4b4b4(Te6edf3CMD_RESETTb4b4b4, Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[Te6edf3CMD_RESET_BYTETb4b4b4]Tb4b4b4)Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
T8b949e// Called after the underlying transport reconnects (post-reboot). Clears
T8b949e// in-flight waiters that will never be answered and re-syncs the KISS decoder
T8b949e// so any half-received frame from before the disconnect doesn't corrupt the
T8b949e// first bytes of the new session.
Te6edf3resetSessionTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72for Tb4b4b4(Tff7b72const Tb4b4b4[Tb4b4b4, Te6edf3wTb4b4b4] Tff7b72of Tff7b72thisTb4b4b4.Te6edf3waitersTb4b4b4) Tb4b4b4{
Te6edf3clearTimeoutTb4b4b4(Te6edf3wTb4b4b4.Te6edf3timeoutIdTb4b4b4)Tb4b4b4;
Tff7b72try Tb4b4b4{ Te6edf3wTb4b4b4.Te6edf3rejectTb4b4b4(Tff7b72new Tf85149ErrorTb4b4b4(Ta5d6ff'connection lost'Tb4b4b4)Tb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4}
Tb4b4b4}
Tff7b72thisTb4b4b4.Te6edf3waitersTb4b4b4.Te6edf3clearTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3decoder Tff7b72= Tff7b72new Te6edf3KissDecoderTb4b4b4(Tb4b4b4(Te6edf3cmdTb4b4b4, Te6edf3payloadTb4b4b4) Tb4b4b4=> Tff7b72thisTb4b4b4.Te6edf3_onFrameTb4b4b4(Te6edf3cmdTb4b4b4, Te6edf3payloadTb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3tTb4b4b4.Te6edf3onBytes Tff7b72= Tb4b4b4(Te6edf3bTb4b4b4) Tb4b4b4=> Tff7b72thisTb4b4b4.Te6edf3decoderTb4b4b4.Te6edf3feedTb4b4b4(Te6edf3bTb4b4b4)Tb4b4b4;
Tff7b72thisTb4b4b4.Te6edf3seq Tff7b72= T79c0ff1Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72function Te6edf3packTypedValueTb4b4b4(Te6edf3pTb4b4b4, Te6edf3typeTb4b4b4, Te6edf3vTb4b4b4)Tb4b4b4{
Tff7b72switch Tb4b4b4(Te6edf3typeTb4b4b4) Tb4b4b4{
Tff7b72case Te6edf3FTTb4b4b4.Te6edf3BoolTff7b72: Te6edf3pTb4b4b4.Te6edf3boolTb4b4b4(Tff7b72!Tff7b72!Te6edf3vTb4b4b4)Tb4b4b4; Tff7b72returnTb4b4b4;
Tff7b72case Te6edf3FTTb4b4b4.Te6edf3IntTff7b72: Tff7b72case Te6edf3FTTb4b4b4.Te6edf3EnumTff7b72: Te6edf3pTb4b4b4.Tff7b72intTb4b4b4(Te6edf3vTb4b4b4)Tb4b4b4; Tff7b72returnTb4b4b4;
Tff7b72case Te6edf3FTTb4b4b4.Te6edf3FloatTff7b72: Te6edf3pTb4b4b4.Tff7b72floatTb4b4b4(Tffa657NumberTb4b4b4(Te6edf3vTb4b4b4)Tb4b4b4)Tb4b4b4; Tff7b72returnTb4b4b4;
Tff7b72case Te6edf3FTTb4b4b4.Tffa657StringTff7b72: Te6edf3pTb4b4b4.Te6edf3strTb4b4b4(Tffa657StringTb4b4b4(Te6edf3v Tff7b72== Tff7b72null Tff7b72? Ta5d6ff'' Tff7b72: Te6edf3vTb4b4b4)Tb4b4b4)Tb4b4b4; Tff7b72returnTb4b4b4;
Tff7b72case Te6edf3FTTb4b4b4.Te6edf3BytesTff7b72: Te6edf3pTb4b4b4.Te6edf3binTb4b4b4(Te6edf3v Tff7b72instanceof Tffa657Uint8Array Tff7b72? Te6edf3v Tff7b72: Tff7b72new Tffa657Uint8ArrayTb4b4b4(Te6edf3v Tff7b72|| Tb4b4b4[Tb4b4b4]Tb4b4b4)Tb4b4b4)Tb4b4b4; Tff7b72returnTb4b4b4;
Tff7b72case Te6edf3FTTb4b4b4.Te6edf3BytesListTff7b72: Tb4b4b4{
T8b949e// Wire form: MsgPack array of bin entries. JS form: array of Uint8Array.
Tff7b72const Te6edf3list Tff7b72= Tffa657ArrayTb4b4b4.Te6edf3isArrayTb4b4b4(Te6edf3vTb4b4b4) Tff7b72? Te6edf3v Tff7b72: Tb4b4b4[Tb4b4b4]Tb4b4b4;
Te6edf3pTb4b4b4.Te6edf3arrTb4b4b4(Te6edf3listTb4b4b4.Te6edf3lengthTb4b4b4)Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3e Tff7b72of Te6edf3listTb4b4b4) Te6edf3pTb4b4b4.Te6edf3binTb4b4b4(Te6edf3e Tff7b72instanceof Tffa657Uint8Array Tff7b72? Te6edf3e Tff7b72: Tff7b72new Tffa657Uint8ArrayTb4b4b4(Te6edf3e Tff7b72|| Tb4b4b4[Tb4b4b4]Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72returnTb4b4b4;
Tb4b4b4}
Tff7b72case Te6edf3FTTb4b4b4.Te6edf3VoidTff7b72: Te6edf3pTb4b4b4.Te6edf3nilTb4b4b4(Tb4b4b4)Tb4b4b4; Tff7b72returnTb4b4b4; T8b949e// Argument-less command marker.
Tff7b72defaultTff7b72: Te6edf3pTb4b4b4.Te6edf3nilTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}

T8b949e// ===== Legacy (rnodeconf-style) client =====
T8b949e// Speaks individual KISS opcodes for EEPROM-backed settings: radio, bluetooth,
T8b949e// wifi, display, identity, EEPROM ops. Reuses the same transport/decoder via a
T8b949e// fallthrough subscription on ProvisioningClient.onLegacyFrame.
Tff7b72class Te6edf3LegacyClient Tb4b4b4{
Tff7b72constructorTb4b4b4(Te6edf3provisioningClientTb4b4b4, Te6edf3transportTb4b4b4)Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3t Tff7b72= Te6edf3transportTb4b4b4;
T8b949e// cmd → array of pending {resolve, reject, timeoutId} (FIFO). For each
T8b949e// incoming frame with that cmd, the oldest pending handler resolves with
T8b949e// the payload. Most reads are one-shot, but we use a list to be safe
T8b949e// against rapid-fire queries.
Tff7b72thisTb4b4b4.Te6edf3pending Tff7b72= Tff7b72new Tffa657MapTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3provisioningClientTb4b4b4.Te6edf3onLegacyFrame Tff7b72= Tb4b4b4(Te6edf3cmdTb4b4b4, Te6edf3payloadTb4b4b4) Tb4b4b4=> Tff7b72thisTb4b4b4.Te6edf3_onFrameTb4b4b4(Te6edf3cmdTb4b4b4, Te6edf3payloadTb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3_onFrameTb4b4b4(Te6edf3cmdTb4b4b4, Te6edf3payloadTb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3q Tff7b72= Tff7b72thisTb4b4b4.Te6edf3pendingTb4b4b4.Te6edf3getTb4b4b4(Te6edf3cmdTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3q Tff7b72|| Te6edf3qTb4b4b4.Te6edf3length Tff7b72=== T79c0ff0Tb4b4b4) Tff7b72returnTb4b4b4;
Tff7b72const Te6edf3w Tff7b72= Te6edf3qTb4b4b4.Te6edf3shiftTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3qTb4b4b4.Te6edf3length Tff7b72=== T79c0ff0Tb4b4b4) Tff7b72thisTb4b4b4.Te6edf3pendingTb4b4b4.Tff7b72deleteTb4b4b4(Te6edf3cmdTb4b4b4)Tb4b4b4;
Te6edf3clearTimeoutTb4b4b4(Te6edf3wTb4b4b4.Te6edf3timeoutIdTb4b4b4)Tb4b4b4;
Te6edf3wTb4b4b4.Te6edf3resolveTb4b4b4(Te6edf3payloadTb4b4b4)Tb4b4b4;
Tb4b4b4}
T8b949e// Drop all pending queries with "connection lost" — called from
T8b949e// ProvisioningClient.resetSession (post-reboot).
Te6edf3resetSessionTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72for Tb4b4b4(Tff7b72const Tb4b4b4[Tb4b4b4, Te6edf3qTb4b4b4] Tff7b72of Tff7b72thisTb4b4b4.Te6edf3pendingTb4b4b4) Tb4b4b4{
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3w Tff7b72of Te6edf3qTb4b4b4) Tb4b4b4{ Te6edf3clearTimeoutTb4b4b4(Te6edf3wTb4b4b4.Te6edf3timeoutIdTb4b4b4)Tb4b4b4; Tff7b72try Tb4b4b4{ Te6edf3wTb4b4b4.Te6edf3rejectTb4b4b4(Tff7b72new Tf85149ErrorTb4b4b4(Ta5d6ff'connection lost'Tb4b4b4)Tb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4} Tb4b4b4}
Tb4b4b4}
Tff7b72thisTb4b4b4.Te6edf3pendingTb4b4b4.Te6edf3clearTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72async Te6edf3writeTb4b4b4(Te6edf3cmdTb4b4b4, Te6edf3payloadTb4b4b4)Tb4b4b4{
Tff7b72let Te6edf3p Tff7b72= Te6edf3payload Tff7b72instanceof Tffa657Uint8Array Tff7b72? Te6edf3payload Tff7b72: Tff7b72new Tffa657Uint8ArrayTb4b4b4(Te6edf3payload Tff7b72|| Tb4b4b4[Tb4b4b4]Tb4b4b4)Tb4b4b4;
T8b949e// The firmware's serial dispatcher fires its handlers per-byte INSIDE the
T8b949e// frame, not on frame end. For parameterless commands (CMD_CONF_SAVE,
T8b949e// CMD_CONF_DELETE, CMD_ROM_READ, CMD_CFG_READ, etc.) the handler is keyed
T8b949e// on `command == X` and runs against each payload byte; with a zero-byte
T8b949e// payload it never runs. Pad with a single 0x00 sentinel — every such
T8b949e// handler ignores the byte's value.
Tff7b72if Tb4b4b4(Te6edf3pTb4b4b4.Te6edf3length Tff7b72=== T79c0ff0Tb4b4b4) Te6edf3p Tff7b72= Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[T79c0ff0x00Tb4b4b4]Tb4b4b4)Tb4b4b4;
Tff7b72await Tff7b72thisTb4b4b4.Te6edf3tTb4b4b4.Te6edf3sendTb4b4b4(Te6edf3kissEncodeTb4b4b4(Te6edf3cmdTb4b4b4, Te6edf3pTb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
T8b949e// Query: send the opcode with `queryPayload` and resolve when the device
T8b949e// echoes back a frame with the same opcode. Timeout is short by default
T8b949e// because most rnodeconf queries respond within tens of ms.
Te6edf3queryTb4b4b4(Te6edf3cmdTb4b4b4, Te6edf3queryPayloadTb4b4b4, Te6edf3timeoutMsTb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3timeout Tff7b72= Te6edf3timeoutMs Tff7b72!= Tff7b72null Tff7b72? Te6edf3timeoutMs Tff7b72: T79c0ff1500Tb4b4b4;
Tff7b72return Tff7b72new Tffa657PromiseTb4b4b4(Tb4b4b4(Te6edf3resolveTb4b4b4, Te6edf3rejectTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3w Tff7b72= Tb4b4b4{ Te6edf3resolveTb4b4b4, Te6edf3reject Tb4b4b4}Tb4b4b4;
Te6edf3wTb4b4b4.Te6edf3timeoutId Tff7b72= Te6edf3setTimeoutTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3q Tff7b72= Tff7b72thisTb4b4b4.Te6edf3pendingTb4b4b4.Te6edf3getTb4b4b4(Te6edf3cmdTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3qTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3i Tff7b72= Te6edf3qTb4b4b4.Te6edf3indexOfTb4b4b4(Te6edf3wTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3i Tff7b72>= T79c0ff0Tb4b4b4) Te6edf3qTb4b4b4.Te6edf3spliceTb4b4b4(Te6edf3iTb4b4b4, T79c0ff1Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3qTb4b4b4.Te6edf3length Tff7b72=== T79c0ff0Tb4b4b4) Tff7b72thisTb4b4b4.Te6edf3pendingTb4b4b4.Tff7b72deleteTb4b4b4(Te6edf3cmdTb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3rejectTb4b4b4(Tff7b72new Tf85149ErrorTb4b4b4(Ta5d6ff'legacy query timed out (cmd 0x'Tff7b72+Te6edf3cmdTb4b4b4.Te6edf3toStringTb4b4b4(T79c0ff16Tb4b4b4)Tff7b72+Ta5d6ff')'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4, Te6edf3timeoutTb4b4b4)Tb4b4b4;
Tff7b72let Te6edf3q Tff7b72= Tff7b72thisTb4b4b4.Te6edf3pendingTb4b4b4.Te6edf3getTb4b4b4(Te6edf3cmdTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3qTb4b4b4) Tb4b4b4{ Te6edf3q Tff7b72= Tb4b4b4[Tb4b4b4]Tb4b4b4; Tff7b72thisTb4b4b4.Te6edf3pendingTb4b4b4.Te6edf3setTb4b4b4(Te6edf3cmdTb4b4b4, Te6edf3qTb4b4b4)Tb4b4b4; Tb4b4b4}
Te6edf3qTb4b4b4.Te6edf3pushTb4b4b4(Te6edf3wTb4b4b4)Tb4b4b4;
Tffa657PromiseTb4b4b4.Te6edf3resolveTb4b4b4(Tff7b72thisTb4b4b4.Te6edf3writeTb4b4b4(Te6edf3cmdTb4b4b4, Te6edf3queryPayloadTb4b4b4)Tb4b4b4)Tb4b4b4.Tff7b72catchTb4b4b4(Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4=> Tb4b4b4{
Te6edf3clearTimeoutTb4b4b4(Te6edf3wTb4b4b4.Te6edf3timeoutIdTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3arr Tff7b72= Tff7b72thisTb4b4b4.Te6edf3pendingTb4b4b4.Te6edf3getTb4b4b4(Te6edf3cmdTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3arrTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3i Tff7b72= Te6edf3arrTb4b4b4.Te6edf3indexOfTb4b4b4(Te6edf3wTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3i Tff7b72>= T79c0ff0Tb4b4b4) Te6edf3arrTb4b4b4.Te6edf3spliceTb4b4b4(Te6edf3iTb4b4b4, T79c0ff1Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3arrTb4b4b4.Te6edf3length Tff7b72=== T79c0ff0Tb4b4b4) Tff7b72thisTb4b4b4.Te6edf3pendingTb4b4b4.Tff7b72deleteTb4b4b4(Te6edf3cmdTb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3rejectTb4b4b4(Te6edf3eTb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}
T8b949e// Read one field per the NODE_CONFIG_SCHEMA entry.
Tff7b72async Te6edf3readFieldTb4b4b4(Te6edf3fTb4b4b4)Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3fTb4b4b4.Te6edf3readable Tff7b72=== Tff7b72falseTb4b4b4) Tff7b72return Tff7b72undefinedTb4b4b4;
Tff7b72const Te6edf3enc Tff7b72= Te6edf3NCFG_ENCTb4b4b4[Te6edf3fTb4b4b4.Te6edf3encodingTb4b4b4]Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3enc Tff7b72|| Tff7b72!Te6edf3encTb4b4b4.Te6edf3queryTb4b4b4) Tff7b72return Tff7b72undefinedTb4b4b4;
Tff7b72const Te6edf3reply Tff7b72= Tff7b72await Tff7b72thisTb4b4b4.Te6edf3queryTb4b4b4(Te6edf3fTb4b4b4.Te6edf3cmdTb4b4b4, Te6edf3encTb4b4b4.Te6edf3queryTb4b4b4(Tb4b4b4)Tb4b4b4, T79c0ff1500Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3encTb4b4b4.Te6edf3decTb4b4b4) Tff7b72return Tff7b72undefinedTb4b4b4;
Tff7b72const Te6edf3raw Tff7b72= Te6edf3encTb4b4b4.Te6edf3decTb4b4b4(Te6edf3replyTb4b4b4)Tb4b4b4;
Tff7b72return Tb4b4b4(Te6edf3fTb4b4b4.Te6edf3fromWireTb4b4b4) Tff7b72? Te6edf3fTb4b4b4.Te6edf3fromWireTb4b4b4(Te6edf3rawTb4b4b4) Tff7b72: Te6edf3rawTb4b4b4;
Tb4b4b4}
T8b949e// Encode one field value for the wire (does NOT send it).
Te6edf3encodeFieldTb4b4b4(Te6edf3fTb4b4b4, Te6edf3valueTb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3enc Tff7b72= Te6edf3NCFG_ENCTb4b4b4[Te6edf3fTb4b4b4.Te6edf3encodingTb4b4b4]Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3encTb4b4b4) Tff7b72throw Tff7b72new Tf85149ErrorTb4b4b4(Ta5d6ff'unknown encoding ' Tff7b72+ Te6edf3fTb4b4b4.Te6edf3encodingTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3wireVal Tff7b72= Tb4b4b4(Te6edf3fTb4b4b4.Te6edf3toWireTb4b4b4) Tff7b72? Te6edf3fTb4b4b4.Te6edf3toWireTb4b4b4(Te6edf3valueTb4b4b4) Tff7b72: Te6edf3valueTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3fTb4b4b4.Te6edf3encoding Tff7b72=== Ta5d6ff'str'Tb4b4b4) Tff7b72return Te6edf3encTb4b4b4.Te6edf3encStrTb4b4b4(Te6edf3wireValTb4b4b4, Te6edf3fTb4b4b4.Te6edf3maxLen Tff7b72|| T79c0ff32Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3fTb4b4b4.Te6edf3encoding Tff7b72=== Ta5d6ff'ip4'Tb4b4b4) Tff7b72return Te6edf3encTb4b4b4.Te6edf3encTb4b4b4(Te6edf3wireValTb4b4b4)Tb4b4b4;
Tff7b72return Te6edf3encTb4b4b4.Te6edf3encTb4b4b4(Te6edf3wireValTb4b4b4)Tb4b4b4;
Tb4b4b4}
T8b949e// Read all fields in a section. Returns { fieldId: value } map.
Tff7b72async Te6edf3readSectionTb4b4b4(Te6edf3sectionIdTb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3sec Tff7b72= Te6edf3NODE_CONFIG_SCHEMATb4b4b4[Te6edf3sectionIdTb4b4b4]Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3sec Tff7b72|| Tff7b72!Te6edf3secTb4b4b4.Te6edf3fieldsTb4b4b4) Tff7b72return Tb4b4b4{Tb4b4b4}Tb4b4b4;
Tff7b72const Te6edf3out Tff7b72= Tb4b4b4{Tb4b4b4}Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3f Tff7b72of Te6edf3secTb4b4b4.Te6edf3fieldsTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3fTb4b4b4.Te6edf3readable Tff7b72=== Tff7b72falseTb4b4b4) Tff7b72continueTb4b4b4;
Tff7b72try Tb4b4b4{
Tff7b72const Te6edf3v Tff7b72= Tff7b72await Tff7b72thisTb4b4b4.Te6edf3readFieldTb4b4b4(Te6edf3fTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3v Tff7b72!== Tff7b72undefinedTb4b4b4) Te6edf3outTb4b4b4[Te6edf3fTb4b4b4.Te6edf3idTb4b4b4] Tff7b72= Te6edf3vTb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{
T8b949e// Field doesn't reply — skip. UI will show it as empty / default.
Tb4b4b4}
Tb4b4b4}
Tff7b72return Te6edf3outTb4b4b4;
Tb4b4b4}
T8b949e// Write only the drafted fields in a section, in saveOrder. Each write is a
T8b949e// fire-and-forget KISS frame. The schema may declare:
T8b949e// - saveLeader: array of {cmd, payload} ops fired BEFORE field writes.
T8b949e// - saveTrailer: {cmd, payload} OR array of such ops, fired AFTER field
T8b949e// writes. Used by the radio section to first bring the radio online
T8b949e// (CMD_RADIO_STATE 0x01) and then persist (CMD_CONF_SAVE).
Tff7b72async Te6edf3writeSectionTb4b4b4(Te6edf3sectionIdTb4b4b4, Te6edf3draftTb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3sec Tff7b72= Te6edf3NODE_CONFIG_SCHEMATb4b4b4[Te6edf3sectionIdTb4b4b4]Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3sec Tff7b72|| Tff7b72!Te6edf3secTb4b4b4.Te6edf3fieldsTb4b4b4) Tff7b72returnTb4b4b4;
Tff7b72if Tb4b4b4(Tffa657ArrayTb4b4b4.Te6edf3isArrayTb4b4b4(Te6edf3secTb4b4b4.Te6edf3saveLeaderTb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3op Tff7b72of Te6edf3secTb4b4b4.Te6edf3saveLeaderTb4b4b4) Tff7b72await Tff7b72thisTb4b4b4.Te6edf3writeTb4b4b4(Te6edf3opTb4b4b4.Te6edf3cmdTb4b4b4, Te6edf3opTb4b4b4.Te6edf3payload Tff7b72|| Tff7b72new Tffa657Uint8ArrayTb4b4b4(T79c0ff0Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72const Te6edf3order Tff7b72= Te6edf3secTb4b4b4.Te6edf3saveOrder Tff7b72|| Te6edf3secTb4b4b4.Te6edf3fieldsTb4b4b4.Te6edf3mapTb4b4b4(Te6edf3f Tb4b4b4=> Te6edf3fTb4b4b4.Te6edf3idTb4b4b4)Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3fid Tff7b72of Te6edf3orderTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Tb4b4b4(Te6edf3fid Tff7b72in Te6edf3draftTb4b4b4)Tb4b4b4) Tff7b72continueTb4b4b4;
Tff7b72const Te6edf3f Tff7b72= Te6edf3secTb4b4b4.Te6edf3fieldsTb4b4b4.Te6edf3findTb4b4b4(Te6edf3ff Tb4b4b4=> Te6edf3ffTb4b4b4.Te6edf3id Tff7b72=== Te6edf3fidTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3fTb4b4b4) Tff7b72continueTb4b4b4;
Tff7b72const Te6edf3bytes Tff7b72= Tff7b72thisTb4b4b4.Te6edf3encodeFieldTb4b4b4(Te6edf3fTb4b4b4, Te6edf3draftTb4b4b4[Te6edf3fidTb4b4b4]Tb4b4b4)Tb4b4b4;
Tff7b72await Tff7b72thisTb4b4b4.Te6edf3writeTb4b4b4(Te6edf3fTb4b4b4.Te6edf3cmdTb4b4b4, Te6edf3bytesTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3secTb4b4b4.Te6edf3saveTrailerTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3ops Tff7b72= Tffa657ArrayTb4b4b4.Te6edf3isArrayTb4b4b4(Te6edf3secTb4b4b4.Te6edf3saveTrailerTb4b4b4) Tff7b72? Te6edf3secTb4b4b4.Te6edf3saveTrailer Tff7b72: Tb4b4b4[Te6edf3secTb4b4b4.Te6edf3saveTrailerTb4b4b4]Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3op Tff7b72of Te6edf3opsTb4b4b4) Tff7b72await Tff7b72thisTb4b4b4.Te6edf3writeTb4b4b4(Te6edf3opTb4b4b4.Te6edf3cmdTb4b4b4, Te6edf3opTb4b4b4.Te6edf3payload Tff7b72|| Tff7b72new Tffa657Uint8ArrayTb4b4b4(T79c0ff0Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72async Te6edf3readEepromTb4b4b4(Tb4b4b4)Tb4b4b4{
T8b949e// CMD_ROM_READ replies in a single frame with all 200 EEPROM bytes.
Tff7b72return Tff7b72await Tff7b72thisTb4b4b4.Te6edf3queryTb4b4b4(Te6edf3CMD_ROM_READTb4b4b4, Tff7b72new Tffa657Uint8ArrayTb4b4b4(T79c0ff0Tb4b4b4)Tb4b4b4, T79c0ff3000Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72async Te6edf3readCfgSectorTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72return Tff7b72await Tff7b72thisTb4b4b4.Te6edf3queryTb4b4b4(Te6edf3CMD_CFG_READTb4b4b4, Tff7b72new Tffa657Uint8ArrayTb4b4b4(T79c0ff0Tb4b4b4)Tb4b4b4, T79c0ff3000Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72async Te6edf3wipeEepromTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72await Tff7b72thisTb4b4b4.Te6edf3writeTb4b4b4(Te6edf3CMD_UNLOCK_ROMTb4b4b4, Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[Te6edf3ROM_UNLOCK_BYTETb4b4b4]Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72async Te6edf3setModeTb4b4b4(Te6edf3tncTb4b4b4)Tb4b4b4{
T8b949e// CMD_CONF_SAVE persists radio settings AND sets ADDR_CONF_OK=0x73 (next
T8b949e// boot enters TNC mode). CMD_CONF_DELETE clears that marker.
T8b949e// Switching to TNC requires the radio to be online — eeprom_conf_save()
T8b949e// short-circuits unless radio_online == true. CMD_CONF_DELETE just clears
T8b949e// a byte and doesn't need the radio.
Tff7b72if Tb4b4b4(Te6edf3tncTb4b4b4) Tff7b72await Tff7b72thisTb4b4b4.Te6edf3writeTb4b4b4(Te6edf3CMD_RADIO_STATETb4b4b4, Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[T79c0ff0x01Tb4b4b4]Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72await Tff7b72thisTb4b4b4.Te6edf3writeTb4b4b4(Te6edf3tnc Tff7b72? Te6edf3CMD_CONF_SAVE Tff7b72: Te6edf3CMD_CONF_DELETETb4b4b4, Tff7b72new Tffa657Uint8ArrayTb4b4b4(T79c0ff0Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72async Te6edf3setBluetoothTb4b4b4(Te6edf3modeTb4b4b4)Tb4b4b4{
T8b949e// mode: 0=off, 1=on, 2=pairing
Tff7b72await Tff7b72thisTb4b4b4.Te6edf3writeTb4b4b4(Te6edf3CMD_BT_CTRLTb4b4b4, Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[Te6edf3mode Tff7b72& T79c0ff0xffTb4b4b4]Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72async Te6edf3bluetoothUnpairTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72await Tff7b72thisTb4b4b4.Te6edf3writeTb4b4b4(Te6edf3CMD_BT_UNPAIRTb4b4b4, Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[T79c0ff0x01Tb4b4b4]Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72async Te6edf3reconditionDisplayTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72await Tff7b72thisTb4b4b4.Te6edf3writeTb4b4b4(Te6edf3CMD_DISP_RCNDTb4b4b4, Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[T79c0ff0x01Tb4b4b4]Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
T8b949e// Read the Device Info sub-tab: board, platform, MCU, firmware version, hashes.
Tff7b72async Te6edf3readDeviceInfoTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3info Tff7b72= Tb4b4b4{Tb4b4b4}Tb4b4b4;
Tff7b72const Te6edf3tryGet Tff7b72= Tff7b72async Tb4b4b4(Te6edf3cmdTb4b4b4, Te6edf3queryPayloadTb4b4b4, Te6edf3timeoutTb4b4b4, Te6edf3parserTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72try Tb4b4b4{
Tff7b72const Te6edf3reply Tff7b72= Tff7b72await Tff7b72thisTb4b4b4.Te6edf3queryTb4b4b4(Te6edf3cmdTb4b4b4, Te6edf3queryPayloadTb4b4b4, Te6edf3timeout Tff7b72|| T79c0ff1500Tb4b4b4)Tb4b4b4;
Tff7b72return Te6edf3parser Tff7b72? Te6edf3parserTb4b4b4(Te6edf3replyTb4b4b4) Tff7b72: Te6edf3replyTb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{ Tff7b72return Tff7b72nullTb4b4b4; Tb4b4b4}
Tb4b4b4}Tb4b4b4;
Te6edf3infoTb4b4b4.Te6edf3board Tff7b72= Tff7b72await Te6edf3tryGetTb4b4b4(Te6edf3CMD_BOARDTb4b4b4, Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4)Tb4b4b4, T79c0ff1500Tb4b4b4, Tb4b4b4(Te6edf3bTb4b4b4) Tb4b4b4=> Te6edf3bTb4b4b4.Te6edf3length Tff7b72>= T79c0ff1 Tff7b72? Te6edf3bTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72: Tff7b72nullTb4b4b4)Tb4b4b4;
Te6edf3infoTb4b4b4.Te6edf3platform Tff7b72= Tff7b72await Te6edf3tryGetTb4b4b4(Te6edf3CMD_PLATFORMTb4b4b4, Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4)Tb4b4b4, T79c0ff1500Tb4b4b4, Tb4b4b4(Te6edf3bTb4b4b4) Tb4b4b4=> Te6edf3bTb4b4b4.Te6edf3length Tff7b72>= T79c0ff1 Tff7b72? Te6edf3bTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72: Tff7b72nullTb4b4b4)Tb4b4b4;
Te6edf3infoTb4b4b4.Te6edf3mcu Tff7b72= Tff7b72await Te6edf3tryGetTb4b4b4(Te6edf3CMD_MCUTb4b4b4, Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4)Tb4b4b4, T79c0ff1500Tb4b4b4, Tb4b4b4(Te6edf3bTb4b4b4) Tb4b4b4=> Te6edf3bTb4b4b4.Te6edf3length Tff7b72>= T79c0ff1 Tff7b72? Te6edf3bTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72: Tff7b72nullTb4b4b4)Tb4b4b4;
T8b949e// Firmware version: MAJ_VERS and MIN_VERS are emitted as raw bytes which
T8b949e// rnodeconf treats as decimal (e.g. MIN_VERS=0x56 → "86", not "56").
Te6edf3infoTb4b4b4.Te6edf3fwVersion Tff7b72= Tff7b72await Te6edf3tryGetTb4b4b4(Te6edf3CMD_FW_VERSIONTb4b4b4, Tff7b72new Tffa657Uint8ArrayTb4b4b4(T79c0ff0Tb4b4b4)Tb4b4b4, T79c0ff1500Tb4b4b4, Tb4b4b4(Te6edf3bTb4b4b4) Tb4b4b4=> Te6edf3bTb4b4b4.Te6edf3length Tff7b72>= T79c0ff2 Tff7b72? Ta5d6ff`Tffd700${Te6edf3bTb4b4b4[T79c0ff0Tb4b4b4]Tffd700}Ta5d6ff.Tffd700${Te6edf3bTb4b4b4[T79c0ff1Tb4b4b4]Tb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3padStartTb4b4b4(T79c0ff2Tb4b4b4,Ta5d6ff'0'Tb4b4b4)Tffd700}Ta5d6ff` Tff7b72: Tff7b72nullTb4b4b4)Tb4b4b4;
Te6edf3infoTb4b4b4.Te6edf3devHash Tff7b72= Tff7b72await Te6edf3tryGetTb4b4b4(Te6edf3CMD_DEV_HASHTb4b4b4, Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[T79c0ff0x01Tb4b4b4]Tb4b4b4)Tb4b4b4, T79c0ff1500Tb4b4b4, Tb4b4b4(Te6edf3bTb4b4b4) Tb4b4b4=> Te6edf3bTb4b4b4)Tb4b4b4;
T8b949e// CMD_HASHES: 0x01=target FW, 0x02=actual FW, 0x03=bootloader, 0x04=partition.
T8b949e// Each response is 33 bytes: [type_byte, 32 bytes hash]. Use a single query per type.
T8b949e// The cmd dispatcher's per-cmd FIFO means concurrent queries on the same cmd
T8b949e// would race; serialize them sequentially.
Te6edf3infoTb4b4b4.Te6edf3fwHashTarget Tff7b72= Tff7b72await Te6edf3tryGetTb4b4b4(Te6edf3CMD_HASHESTb4b4b4, Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[T79c0ff0x01Tb4b4b4]Tb4b4b4)Tb4b4b4, T79c0ff1500Tb4b4b4, Tb4b4b4(Te6edf3bTb4b4b4) Tb4b4b4=> Te6edf3b Tff7b72&& Te6edf3bTb4b4b4.Te6edf3length Tff7b72>= T79c0ff33 Tff7b72? Te6edf3bTb4b4b4.Te6edf3sliceTb4b4b4(T79c0ff1Tb4b4b4, T79c0ff33Tb4b4b4) Tff7b72: Tff7b72nullTb4b4b4)Tb4b4b4;
Te6edf3infoTb4b4b4.Te6edf3fwHashActual Tff7b72= Tff7b72await Te6edf3tryGetTb4b4b4(Te6edf3CMD_HASHESTb4b4b4, Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[T79c0ff0x02Tb4b4b4]Tb4b4b4)Tb4b4b4, T79c0ff1500Tb4b4b4, Tb4b4b4(Te6edf3bTb4b4b4) Tb4b4b4=> Te6edf3b Tff7b72&& Te6edf3bTb4b4b4.Te6edf3length Tff7b72>= T79c0ff33 Tff7b72? Te6edf3bTb4b4b4.Te6edf3sliceTb4b4b4(T79c0ff1Tb4b4b4, T79c0ff33Tb4b4b4) Tff7b72: Tff7b72nullTb4b4b4)Tb4b4b4;
Te6edf3infoTb4b4b4.Te6edf3bootloaderHash Tff7b72= Tff7b72await Te6edf3tryGetTb4b4b4(Te6edf3CMD_HASHESTb4b4b4, Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[T79c0ff0x03Tb4b4b4]Tb4b4b4)Tb4b4b4, T79c0ff1500Tb4b4b4, Tb4b4b4(Te6edf3bTb4b4b4) Tb4b4b4=> Te6edf3b Tff7b72&& Te6edf3bTb4b4b4.Te6edf3length Tff7b72>= T79c0ff33 Tff7b72? Te6edf3bTb4b4b4.Te6edf3sliceTb4b4b4(T79c0ff1Tb4b4b4, T79c0ff33Tb4b4b4) Tff7b72: Tff7b72nullTb4b4b4)Tb4b4b4;
Te6edf3infoTb4b4b4.Te6edf3partitionHash Tff7b72= Tff7b72await Te6edf3tryGetTb4b4b4(Te6edf3CMD_HASHESTb4b4b4, Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[T79c0ff0x04Tb4b4b4]Tb4b4b4)Tb4b4b4, T79c0ff1500Tb4b4b4, Tb4b4b4(Te6edf3bTb4b4b4) Tb4b4b4=> Te6edf3b Tff7b72&& Te6edf3bTb4b4b4.Te6edf3length Tff7b72>= T79c0ff33 Tff7b72? Te6edf3bTb4b4b4.Te6edf3sliceTb4b4b4(T79c0ff1Tb4b4b4, T79c0ff33Tb4b4b4) Tff7b72: Tff7b72nullTb4b4b4)Tb4b4b4;
Tff7b72return Te6edf3infoTb4b4b4;
Tb4b4b4}
Tb4b4b4}

T8b949e// ===== Status decoder =====
Tff7b72function Te6edf3decodeStatusFrameTb4b4b4(Te6edf3cmdTb4b4b4, Te6edf3payloadTb4b4b4, Te6edf3stTb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3dv Tff7b72= Tff7b72new Tffa657DataViewTb4b4b4(Te6edf3payloadTb4b4b4.Te6edf3bufferTb4b4b4, Te6edf3payloadTb4b4b4.Te6edf3byteOffsetTb4b4b4, Te6edf3payloadTb4b4b4.Te6edf3byteLengthTb4b4b4)Tb4b4b4;
Te6edf3stTb4b4b4.Te6edf3_t Tff7b72= Tffa657DateTb4b4b4.Te6edf3nowTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72switch Tb4b4b4(Te6edf3cmdTb4b4b4) Tb4b4b4{
Tff7b72case T79c0ff0x21Tff7b72: Tff7b72if Tb4b4b4(Te6edf3payloadTb4b4b4.Te6edf3lengthTff7b72>=T79c0ff4Tb4b4b4) Te6edf3stTb4b4b4.Te6edf3rxPackets Tff7b72= Te6edf3dvTb4b4b4.Te6edf3getUint32Tb4b4b4(T79c0ff0Tb4b4b4,Tff7b72falseTb4b4b4)Tb4b4b4; Tff7b72breakTb4b4b4;
Tff7b72case T79c0ff0x22Tff7b72: Tff7b72if Tb4b4b4(Te6edf3payloadTb4b4b4.Te6edf3lengthTff7b72>=T79c0ff4Tb4b4b4) Te6edf3stTb4b4b4.Te6edf3txPackets Tff7b72= Te6edf3dvTb4b4b4.Te6edf3getUint32Tb4b4b4(T79c0ff0Tb4b4b4,Tff7b72falseTb4b4b4)Tb4b4b4; Tff7b72breakTb4b4b4;
Tff7b72case T79c0ff0x23Tff7b72: Tff7b72if Tb4b4b4(Te6edf3payloadTb4b4b4.Te6edf3lengthTff7b72>=T79c0ff1Tb4b4b4) Te6edf3stTb4b4b4.Te6edf3lastRssi Tff7b72= Te6edf3payloadTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72- Te6edf3RSSI_OFFSETTb4b4b4; Tff7b72breakTb4b4b4;
Tff7b72case T79c0ff0x24Tff7b72: Tff7b72if Tb4b4b4(Te6edf3payloadTb4b4b4.Te6edf3lengthTff7b72>=T79c0ff1Tb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3raw Tff7b72= Te6edf3payloadTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72< T79c0ff128 Tff7b72? Te6edf3payloadTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72: Te6edf3payloadTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72- T79c0ff256Tb4b4b4;
Te6edf3stTb4b4b4.Te6edf3lastSnr Tff7b72= Te6edf3raw Tff7b72/ T79c0ff4.0Tb4b4b4;
Tb4b4b4} Tff7b72breakTb4b4b4;
Tff7b72case T79c0ff0x25Tff7b72: Tff7b72if Tb4b4b4(Te6edf3payloadTb4b4b4.Te6edf3lengthTff7b72>=T79c0ff11Tb4b4b4) Tb4b4b4{
Te6edf3stTb4b4b4.Te6edf3airtimeShort Tff7b72= Te6edf3dvTb4b4b4.Te6edf3getUint16Tb4b4b4(T79c0ff0Tb4b4b4,Tff7b72falseTb4b4b4) Tff7b72/ T79c0ff10000Tb4b4b4;
Te6edf3stTb4b4b4.Te6edf3airtimeLong Tff7b72= Te6edf3dvTb4b4b4.Te6edf3getUint16Tb4b4b4(T79c0ff2Tb4b4b4,Tff7b72falseTb4b4b4) Tff7b72/ T79c0ff10000Tb4b4b4;
Te6edf3stTb4b4b4.Te6edf3channelUtilShort Tff7b72= Te6edf3dvTb4b4b4.Te6edf3getUint16Tb4b4b4(T79c0ff4Tb4b4b4,Tff7b72falseTb4b4b4) Tff7b72/ T79c0ff10000Tb4b4b4;
Te6edf3stTb4b4b4.Te6edf3channelUtilLong Tff7b72= Te6edf3dvTb4b4b4.Te6edf3getUint16Tb4b4b4(T79c0ff6Tb4b4b4,Tff7b72falseTb4b4b4) Tff7b72/ T79c0ff10000Tb4b4b4;
Te6edf3stTb4b4b4.Te6edf3currentRssi Tff7b72= Te6edf3payloadTb4b4b4[T79c0ff8Tb4b4b4] Tff7b72- Te6edf3RSSI_OFFSETTb4b4b4;
Te6edf3stTb4b4b4.Te6edf3noiseFloor Tff7b72= Te6edf3payloadTb4b4b4[T79c0ff9Tb4b4b4] Tff7b72- Te6edf3RSSI_OFFSETTb4b4b4;
Te6edf3stTb4b4b4.Te6edf3interferenceRssi Tff7b72= Te6edf3payloadTb4b4b4[T79c0ff10Tb4b4b4] Tff7b72=== T79c0ff0xFF Tff7b72? Tff7b72null Tff7b72: Tb4b4b4(Te6edf3payloadTb4b4b4[T79c0ff10Tb4b4b4] Tff7b72- Te6edf3RSSI_OFFSETTb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72breakTb4b4b4;
Tff7b72case T79c0ff0x26Tff7b72: Tff7b72if Tb4b4b4(Te6edf3payloadTb4b4b4.Te6edf3lengthTff7b72>=T79c0ff12Tb4b4b4) Tb4b4b4{
Te6edf3stTb4b4b4.Te6edf3symbolTimeUs Tff7b72= Te6edf3dvTb4b4b4.Te6edf3getUint16Tb4b4b4(T79c0ff0Tb4b4b4,Tff7b72falseTb4b4b4)Tb4b4b4;
Te6edf3stTb4b4b4.Te6edf3symbolRate Tff7b72= Te6edf3dvTb4b4b4.Te6edf3getUint16Tb4b4b4(T79c0ff2Tb4b4b4,Tff7b72falseTb4b4b4)Tb4b4b4;
Te6edf3stTb4b4b4.Te6edf3preambleSymbols Tff7b72= Te6edf3dvTb4b4b4.Te6edf3getUint16Tb4b4b4(T79c0ff4Tb4b4b4,Tff7b72falseTb4b4b4)Tb4b4b4;
Te6edf3stTb4b4b4.Te6edf3preambleTimeMs Tff7b72= Te6edf3dvTb4b4b4.Te6edf3getUint16Tb4b4b4(T79c0ff6Tb4b4b4,Tff7b72falseTb4b4b4)Tb4b4b4;
Te6edf3stTb4b4b4.Te6edf3csmaSlotMs Tff7b72= Te6edf3dvTb4b4b4.Te6edf3getUint16Tb4b4b4(T79c0ff8Tb4b4b4,Tff7b72falseTb4b4b4)Tb4b4b4;
Te6edf3stTb4b4b4.Te6edf3difsMs Tff7b72= Te6edf3dvTb4b4b4.Te6edf3getUint16Tb4b4b4(T79c0ff10Tb4b4b4,Tff7b72falseTb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72breakTb4b4b4;
Tff7b72case T79c0ff0x27Tff7b72: Tff7b72if Tb4b4b4(Te6edf3payloadTb4b4b4.Te6edf3lengthTff7b72>=T79c0ff2Tb4b4b4) Tb4b4b4{ Te6edf3stTb4b4b4.Te6edf3batteryState Tff7b72= Te6edf3payloadTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4; Te6edf3stTb4b4b4.Te6edf3batteryPercent Tff7b72= Te6edf3payloadTb4b4b4[T79c0ff1Tb4b4b4]Tb4b4b4; Tb4b4b4} Tff7b72breakTb4b4b4;
Tff7b72case T79c0ff0x28Tff7b72: Tff7b72if Tb4b4b4(Te6edf3payloadTb4b4b4.Te6edf3lengthTff7b72>=T79c0ff3Tb4b4b4) Tb4b4b4{ Te6edf3stTb4b4b4.Te6edf3cwBand Tff7b72= Te6edf3payloadTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4; Te6edf3stTb4b4b4.Te6edf3cwMin Tff7b72= Te6edf3payloadTb4b4b4[T79c0ff1Tb4b4b4]Tb4b4b4; Te6edf3stTb4b4b4.Te6edf3cwMax Tff7b72= Te6edf3payloadTb4b4b4[T79c0ff2Tb4b4b4]Tb4b4b4; Tb4b4b4} Tff7b72breakTb4b4b4;
Tff7b72case T79c0ff0x29Tff7b72: Tff7b72if Tb4b4b4(Te6edf3payloadTb4b4b4.Te6edf3lengthTff7b72>=T79c0ff1Tb4b4b4) Tb4b4b4{
T8b949e// Firmware adds PMU_TEMP_OFFSET=120 to keep negative temps in unsigned
T8b949e// range. Sentinel = PMU_TEMP_MIN-1 = -31 → byte 89 means "no reading".
Tff7b72const Te6edf3t Tff7b72= Te6edf3payloadTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72- T79c0ff120Tb4b4b4;
Te6edf3stTb4b4b4.Te6edf3temperatureC Tff7b72= Tb4b4b4(Te6edf3t Tff7b72<= Tff7b72-T79c0ff30Tb4b4b4) Tff7b72? Tff7b72null Tff7b72: Te6edf3tTb4b4b4;
Tb4b4b4} Tff7b72breakTb4b4b4;
Tb4b4b4}
Tb4b4b4}

T8b949e// ===== Reactive helper =====
Tff7b72function Te6edf3observableTb4b4b4(Te6edf3initialTb4b4b4)Tb4b4b4{
Tff7b72let Te6edf3v Tff7b72= Te6edf3initialTb4b4b4;
Tff7b72const Te6edf3subs Tff7b72= Tff7b72new Tffa657SetTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72return Tb4b4b4{
Te6edf3getTff7b72: Tb4b4b4(Tb4b4b4) Tb4b4b4=> Te6edf3vTb4b4b4,
Te6edf3setTff7b72: Tb4b4b4(Te6edf3nvTb4b4b4) Tb4b4b4=> Tb4b4b4{ Te6edf3v Tff7b72= Te6edf3nvTb4b4b4; Te6edf3subsTb4b4b4.Te6edf3forEachTb4b4b4(Te6edf3s Tb4b4b4=> Te6edf3sTb4b4b4(Te6edf3vTb4b4b4)Tb4b4b4)Tb4b4b4; Tb4b4b4}Tb4b4b4,
Te6edf3updateTff7b72: Tb4b4b4(Te6edf3fnTb4b4b4) Tb4b4b4=> Tb4b4b4{ Te6edf3fnTb4b4b4(Te6edf3vTb4b4b4)Tb4b4b4; Te6edf3subsTb4b4b4.Te6edf3forEachTb4b4b4(Te6edf3s Tb4b4b4=> Te6edf3sTb4b4b4(Te6edf3vTb4b4b4)Tb4b4b4)Tb4b4b4; Tb4b4b4}Tb4b4b4,
Te6edf3subscribeTff7b72: Tb4b4b4(Te6edf3fnTb4b4b4) Tb4b4b4=> Tb4b4b4{ Te6edf3subsTb4b4b4.Te6edf3addTb4b4b4(Te6edf3fnTb4b4b4)Tb4b4b4; Tff7b72return Tb4b4b4(Tb4b4b4) Tb4b4b4=> Te6edf3subsTb4b4b4.Tff7b72deleteTb4b4b4(Te6edf3fnTb4b4b4)Tb4b4b4; Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4;
Tb4b4b4}
T8b949e// Reflected boolean HTML attributes whose property mirror is the canonical form.
Tff7b72const Te6edf3BOOL_ATTRS Tff7b72= Tb4b4b4{ Te6edf3disabledTff7b72: T79c0ff1Tb4b4b4, Te6edf3checkedTff7b72: T79c0ff1Tb4b4b4, Te6edf3readonlyTff7b72: T79c0ff1Tb4b4b4, Te6edf3requiredTff7b72: T79c0ff1Tb4b4b4, Te6edf3hiddenTff7b72: T79c0ff1Tb4b4b4, Te6edf3selectedTff7b72: T79c0ff1Tb4b4b4, Te6edf3multipleTff7b72: T79c0ff1Tb4b4b4, Te6edf3autofocusTff7b72: T79c0ff1 Tb4b4b4}Tb4b4b4;
Tff7b72function Te6edf3elTb4b4b4(Te6edf3tagTb4b4b4, Te6edf3attrsTb4b4b4, Te6edf3childrenTb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3e Tff7b72= Tffa657documentTb4b4b4.Te6edf3createElementTb4b4b4(Te6edf3tagTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3attrsTb4b4b4) Tff7b72for Tb4b4b4(Tff7b72const Te6edf3k Tff7b72in Te6edf3attrsTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3v Tff7b72= Te6edf3attrsTb4b4b4[Te6edf3kTb4b4b4]Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3v Tff7b72== Tff7b72null Tff7b72|| Te6edf3v Tff7b72=== Tff7b72falseTb4b4b4) Tff7b72continueTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3kTb4b4b4.Te6edf3startsWithTb4b4b4(Ta5d6ff'on'Tb4b4b4) Tff7b72&& Tff7b72typeof Te6edf3v Tff7b72=== Ta5d6ff'function'Tb4b4b4) Te6edf3eTb4b4b4.Te6edf3addEventListenerTb4b4b4(Te6edf3kTb4b4b4.Te6edf3sliceTb4b4b4(T79c0ff2Tb4b4b4)Tb4b4b4.Te6edf3toLowerCaseTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3vTb4b4b4)Tb4b4b4;
Tff7b72else Tff7b72if Tb4b4b4(Te6edf3k Tff7b72=== Ta5d6ff'class'Tb4b4b4) Te6edf3eTb4b4b4.Te6edf3className Tff7b72= Te6edf3vTb4b4b4;
Tff7b72else Tff7b72if Tb4b4b4(Te6edf3k Tff7b72=== Ta5d6ff'style' Tff7b72&& Tff7b72typeof Te6edf3v Tff7b72=== Ta5d6ff'object'Tb4b4b4) Tffa657ObjectTb4b4b4.Te6edf3assignTb4b4b4(Te6edf3eTb4b4b4.Te6edf3styleTb4b4b4, Te6edf3vTb4b4b4)Tb4b4b4;
Tff7b72else Tff7b72if Tb4b4b4(Te6edf3BOOL_ATTRSTb4b4b4[Te6edf3kTb4b4b4]Tb4b4b4) Tb4b4b4{ Te6edf3eTb4b4b4[Te6edf3kTb4b4b4] Tff7b72= Tff7b72trueTb4b4b4; Te6edf3eTb4b4b4.Te6edf3setAttributeTb4b4b4(Te6edf3kTb4b4b4, Ta5d6ff''Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72else Tff7b72if Tb4b4b4(Te6edf3v Tff7b72=== Tff7b72trueTb4b4b4) Te6edf3eTb4b4b4.Te6edf3setAttributeTb4b4b4(Te6edf3kTb4b4b4, Ta5d6ff''Tb4b4b4)Tb4b4b4;
Tff7b72else Te6edf3eTb4b4b4.Te6edf3setAttributeTb4b4b4(Te6edf3kTb4b4b4, Te6edf3vTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3children Tff7b72!= Tff7b72nullTb4b4b4) Tb4b4b4{
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3c Tff7b72of Tb4b4b4(Tffa657ArrayTb4b4b4.Te6edf3isArrayTb4b4b4(Te6edf3childrenTb4b4b4) Tff7b72? Te6edf3children Tff7b72: Tb4b4b4[Te6edf3childrenTb4b4b4]Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3c Tff7b72== Tff7b72null Tff7b72|| Te6edf3c Tff7b72=== Tff7b72falseTb4b4b4) Tff7b72continueTb4b4b4;
Te6edf3eTb4b4b4.Te6edf3appendChildTb4b4b4(Tff7b72typeof Te6edf3c Tff7b72=== Ta5d6ff'object' Tff7b72&& Te6edf3cTb4b4b4.Te6edf3nodeType Tff7b72? Te6edf3c Tff7b72: Tffa657documentTb4b4b4.Te6edf3createTextNodeTb4b4b4(Tffa657StringTb4b4b4(Te6edf3cTb4b4b4)Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72return Te6edf3eTb4b4b4;
Tb4b4b4}

T8b949e// ===== State =====
Tff7b72const Te6edf3state Tff7b72= Tb4b4b4{
Te6edf3transportNameTff7b72: Te6edf3observableTb4b4b4(Ta5d6ff'serial'Tb4b4b4)Tb4b4b4,
Te6edf3wsUrlTff7b72: Te6edf3observableTb4b4b4(Ta5d6ff'ws://localhost:8080'Tb4b4b4)Tb4b4b4,
Te6edf3rnsUrlTff7b72: Te6edf3observableTb4b4b4(Ta5d6ff'wss://127.0.0.1:9337/ws'Tb4b4b4)Tb4b4b4,
Te6edf3rnsDestHashTff7b72: Te6edf3observableTb4b4b4(Ta5d6ff''Tb4b4b4)Tb4b4b4,
Te6edf3rnsAspectTff7b72: Te6edf3observableTb4b4b4(Ta5d6ff'rnstransport.remote.management'Tb4b4b4)Tb4b4b4,
Te6edf3rnsAutoIdentifyTff7b72: Te6edf3observableTb4b4b4(Tff7b72trueTb4b4b4)Tb4b4b4,
Te6edf3connTff7b72: Te6edf3observableTb4b4b4(Tb4b4b4{ Te6edf3stateTff7b72: Ta5d6ff'idle' Tb4b4b4}Tb4b4b4)Tb4b4b4,
Te6edf3infoTff7b72: Te6edf3observableTb4b4b4(Tff7b72nullTb4b4b4)Tb4b4b4,
Te6edf3schemaTff7b72: Te6edf3observableTb4b4b4(Tff7b72nullTb4b4b4)Tb4b4b4,
Te6edf3activeTabTff7b72: Te6edf3observableTb4b4b4(Ta5d6ff'status'Tb4b4b4)Tb4b4b4, T8b949e// 'status' | 'nodeconfig' | 'config' | 'logs'
Te6edf3activeNsTabTff7b72: Te6edf3observableTb4b4b4(Tff7b72nullTb4b4b4)Tb4b4b4, T8b949e// ns_id within Configuration tab
Te6edf3nsStateTff7b72: Te6edf3observableTb4b4b4(Tb4b4b4{Tb4b4b4}Tb4b4b4)Tb4b4b4, T8b949e// { nsId: { committed:{fid:val}, draft:{fid:val} } }
Te6edf3nsLoadedTff7b72: Te6edf3observableTb4b4b4(Tb4b4b4{Tb4b4b4}Tb4b4b4)Tb4b4b4, T8b949e// { nsId: true }
Te6edf3nsLoadingTff7b72: Te6edf3observableTb4b4b4(Tb4b4b4{Tb4b4b4}Tb4b4b4)Tb4b4b4, T8b949e// { nsId: true } while fetch is in flight
Te6edf3nsServerErrorsTff7b72: Te6edf3observableTb4b4b4(Tb4b4b4{Tb4b4b4}Tb4b4b4)Tb4b4b4,
Te6edf3nodeStatusTff7b72: Te6edf3observableTb4b4b4(Tb4b4b4{Tb4b4b4}Tb4b4b4)Tb4b4b4,
Te6edf3hasDraftTff7b72: Te6edf3observableTb4b4b4(Tff7b72falseTb4b4b4)Tb4b4b4,
T8b949e// True when the firmware holds an uncommitted draft. The per-namespace Save
T8b949e// sends edits to the firmware (where they live as a draft); only then does
T8b949e// Commit have anything to apply. Discard all also operates on the firmware
T8b949e// draft, so both buttons gate on this flag, not on local-only edits.
Te6edf3firmwareHasDraftTff7b72: Te6edf3observableTb4b4b4(Tff7b72falseTb4b4b4)Tb4b4b4,
Te6edf3autoReconnectTff7b72: Te6edf3observableTb4b4b4(Tff7b72trueTb4b4b4)Tb4b4b4,
Te6edf3reconnectingTff7b72: Te6edf3observableTb4b4b4(Tff7b72falseTb4b4b4)Tb4b4b4,
T8b949e// Node Config tab — parallel observables to nsState/etc but for legacy-opcode
T8b949e// settings. Keyed by section name ('radio', 'wifi', 'display', …) rather than
T8b949e// numeric ns id.
Te6edf3nodeCfgStateTff7b72: Te6edf3observableTb4b4b4(Tb4b4b4{Tb4b4b4}Tb4b4b4)Tb4b4b4,
Te6edf3nodeCfgLoadedTff7b72: Te6edf3observableTb4b4b4(Tb4b4b4{Tb4b4b4}Tb4b4b4)Tb4b4b4,
Te6edf3nodeCfgLoadingTff7b72: Te6edf3observableTb4b4b4(Tb4b4b4{Tb4b4b4}Tb4b4b4)Tb4b4b4,
Te6edf3nodeCfgHasDraftTff7b72: Te6edf3observableTb4b4b4(Tff7b72falseTb4b4b4)Tb4b4b4,
Te6edf3activeNodeCfgTabTff7b72: Te6edf3observableTb4b4b4(Ta5d6ff'device_info'Tb4b4b4)Tb4b4b4,
T8b949e// Cached EEPROM hex viewer state.
Te6edf3nodeCfgEepromTff7b72: Te6edf3observableTb4b4b4(Tff7b72nullTb4b4b4)Tb4b4b4, T8b949e// Uint8Array(200) or null
Te6edf3nodeCfgCfgSectorTff7b72: Te6edf3observableTb4b4b4(Tff7b72nullTb4b4b4)Tb4b4b4, T8b949e// Uint8Array(256) or null
Te6edf3nodeCfgDeviceInfoTff7b72: Te6edf3observableTb4b4b4(Tff7b72nullTb4b4b4)Tb4b4b4, T8b949e// {board, platform, mcu, fwVersion, ...}
T8b949e// Set true after a Node Config save touched a `requiresReboot` section
T8b949e// (radio, wifi, mode). Drives the "Reboot recommended" banner alongside the
T8b949e// Provisioning info.needsReboot flag. Cleared on reboot/reconnect.
Te6edf3nodeCfgNeedsRebootTff7b72: Te6edf3observableTb4b4b4(Tff7b72falseTb4b4b4)Tb4b4b4,
T8b949e// null = not yet probed; true = device replied to a legacy KISS query
T8b949e// (CMD_BOARD) so the Node Config tab is meaningful; false = no reply within
T8b949e// the probe window (device is likely in TNC mode or speaks a different
T8b949e// protocol). Drives the visibility of the Node Config tab.
Te6edf3legacySupportedTff7b72: Te6edf3observableTb4b4b4(Tff7b72nullTb4b4b4)Tb4b4b4,
Tb4b4b4}Tb4b4b4;
T8b949e// Node Config store context — passed to buildFieldRow/setDraftValue/etc.
Tff7b72const Te6edf3NCFG_CTX Tff7b72= Tb4b4b4{
Te6edf3get Te6edf3stateTb4b4b4(Tb4b4b4)Tb4b4b4{ Tff7b72return Te6edf3stateTb4b4b4.Te6edf3nodeCfgStateTb4b4b4; Tb4b4b4}Tb4b4b4,
Te6edf3get Te6edf3errorsTb4b4b4(Tb4b4b4)Tb4b4b4{ Tff7b72return Tff7b72nullTb4b4b4; Tb4b4b4}Tb4b4b4, T8b949e// Node Config has no server-side per-field errors
Te6edf3get Te6edf3hasDraftTb4b4b4(Tb4b4b4)Tb4b4b4{ Tff7b72return Te6edf3stateTb4b4b4.Te6edf3nodeCfgHasDraftTb4b4b4; Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4;
Tff7b72let Te6edf3transport Tff7b72= Tff7b72nullTb4b4b4;
Tff7b72let Te6edf3client Tff7b72= Tff7b72nullTb4b4b4;
T8b949e// LegacyClient instance — speaks rnodeconf-style KISS opcodes for Node Config.
T8b949e// Co-located with `client`; rebuilt in wireClient() on each (re)connect.
Tff7b72let Te6edf3legacy Tff7b72= Tff7b72nullTb4b4b4;
T8b949e// When true, the next 'closed' / 'idle' transport event should fully tear down
T8b949e// state and NOT trigger auto-reconnect. Set by doDisconnect().
Tff7b72let Te6edf3userInitiatedDisconnect Tff7b72= Tff7b72falseTb4b4b4;
T8b949e// Set during reboot()/auto-reconnect so we know to attempt re-establishment.
Tff7b72let Te6edf3lastTransportName Tff7b72= Tff7b72nullTb4b4b4;
T8b949e// Single in-flight reconnect token. Bumping it cancels the previous attempt.
Tff7b72let Te6edf3reconnectToken Tff7b72= T79c0ff0Tb4b4b4;

Tff7b72function Te6edf3createTransportTb4b4b4(Te6edf3nameTb4b4b4)Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3name Tff7b72=== Ta5d6ff'serial'Tb4b4b4) Tff7b72return Tff7b72new Te6edf3SerialTransportTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3name Tff7b72=== Ta5d6ff'ble'Tb4b4b4) Tff7b72return Tff7b72new Te6edf3BLETransportTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3name Tff7b72=== Ta5d6ff'ws'Tb4b4b4) Tff7b72return Tff7b72new Te6edf3WebSocketTransportTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3name Tff7b72=== Ta5d6ff'rns'Tb4b4b4) Tff7b72return Tff7b72new Te6edf3RnsTransportTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72throw Tff7b72new Tf85149ErrorTb4b4b4(Ta5d6ff'unknown transport ' Tff7b72+ Te6edf3nameTb4b4b4)Tb4b4b4;
Tb4b4b4}

Tff7b72function Te6edf3clearSessionStateTb4b4b4(Tb4b4b4)Tb4b4b4{
Te6edf3stateTb4b4b4.Te6edf3infoTb4b4b4.Te6edf3setTb4b4b4(Tff7b72nullTb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3schemaTb4b4b4.Te6edf3setTb4b4b4(Tff7b72nullTb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3activeNsTabTb4b4b4.Te6edf3setTb4b4b4(Tff7b72nullTb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nsStateTb4b4b4.Te6edf3setTb4b4b4(Tb4b4b4{Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nsLoadedTb4b4b4.Te6edf3setTb4b4b4(Tb4b4b4{Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nsLoadingTb4b4b4.Te6edf3setTb4b4b4(Tb4b4b4{Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nsServerErrorsTb4b4b4.Te6edf3setTb4b4b4(Tb4b4b4{Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nodeStatusTb4b4b4.Te6edf3setTb4b4b4(Tb4b4b4{Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3hasDraftTb4b4b4.Te6edf3setTb4b4b4(Tff7b72falseTb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3firmwareHasDraftTb4b4b4.Te6edf3setTb4b4b4(Tff7b72falseTb4b4b4)Tb4b4b4;
T8b949e// Node Config side
Te6edf3stateTb4b4b4.Te6edf3nodeCfgStateTb4b4b4.Te6edf3setTb4b4b4(Tb4b4b4{Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nodeCfgLoadedTb4b4b4.Te6edf3setTb4b4b4(Tb4b4b4{Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nodeCfgLoadingTb4b4b4.Te6edf3setTb4b4b4(Tb4b4b4{Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nodeCfgHasDraftTb4b4b4.Te6edf3setTb4b4b4(Tff7b72falseTb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nodeCfgEepromTb4b4b4.Te6edf3setTb4b4b4(Tff7b72nullTb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nodeCfgCfgSectorTb4b4b4.Te6edf3setTb4b4b4(Tff7b72nullTb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nodeCfgDeviceInfoTb4b4b4.Te6edf3setTb4b4b4(Tff7b72nullTb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nodeCfgNeedsRebootTb4b4b4.Te6edf3setTb4b4b4(Tff7b72falseTb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3legacySupportedTb4b4b4.Te6edf3setTb4b4b4(Tff7b72nullTb4b4b4)Tb4b4b4;
Tb4b4b4}

T8b949e// Toggle a body class while the auto-reconnect loop is active so CSS can dim
T8b949e// and disable panel-body controls. The tab-strip already disables tab buttons
T8b949e// during reconnect; this extends the same affordance to the panel itself so
T8b949e// the user can't start typing into a field that's about to be overwritten by
T8b949e// the post-reconnect fetch.
Te6edf3stateTb4b4b4.Te6edf3reconnectingTb4b4b4.Te6edf3subscribeTb4b4b4(Tb4b4b4(Te6edf3rTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tffa657documentTb4b4b4.Te6edf3bodyTb4b4b4.Te6edf3classListTb4b4b4.Te6edf3toggleTb4b4b4(Ta5d6ff'is-reconnecting'Tb4b4b4, Tff7b72!Tff7b72!Te6edf3rTb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Tff7b72function Te6edf3wireClientTb4b4b4(Te6edf3cTb4b4b4)Tb4b4b4{
Te6edf3cTb4b4b4.Te6edf3onLog Tff7b72= Tb4b4b4(Te6edf3textTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3lines Tff7b72= Te6edf3textTb4b4b4.Te6edf3splitTb4b4b4(Ta5d6ff/\r?\n/Tb4b4b4)Tb4b4b4.Te6edf3filterTb4b4b4(Te6edf3l Tb4b4b4=> Te6edf3lTb4b4b4.Te6edf3length Tff7b72> T79c0ff0Tb4b4b4)Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3l Tff7b72of Te6edf3linesTb4b4b4) Te6edf3logsBufferTb4b4b4.Te6edf3pushTb4b4b4(Te6edf3lTb4b4b4)Tb4b4b4;
Tff7b72while Tb4b4b4(Te6edf3logsBufferTb4b4b4.Te6edf3length Tff7b72> T79c0ff1000Tb4b4b4) Te6edf3logsBufferTb4b4b4.Te6edf3shiftTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3logsListenersTb4b4b4.Te6edf3forEachTb4b4b4(Te6edf3fn Tb4b4b4=> Te6edf3fnTb4b4b4(Te6edf3linesTb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4;
Te6edf3cTb4b4b4.Te6edf3onStatusFrame Tff7b72= Tb4b4b4(Te6edf3cmdTb4b4b4, Te6edf3payloadTb4b4b4) Tb4b4b4=> Tb4b4b4{
Te6edf3stateTb4b4b4.Te6edf3nodeStatusTb4b4b4.Te6edf3updateTb4b4b4(Te6edf3st Tb4b4b4=> Te6edf3decodeStatusFrameTb4b4b4(Te6edf3cmdTb4b4b4, Te6edf3payloadTb4b4b4, Te6edf3stTb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4;
T8b949e// Node Config legacy-opcode client subscribes to c.onLegacyFrame (set inside
T8b949e// LegacyClient's constructor) and uses the same transport for writes.
Te6edf3legacy Tff7b72= Tff7b72new Te6edf3LegacyClientTb4b4b4(Te6edf3cTb4b4b4, Te6edf3cTb4b4b4.Te6edf3tTb4b4b4)Tb4b4b4;
Tb4b4b4}

Tff7b72function Te6edf3onTransportStatusTb4b4b4(Te6edf3sTb4b4b4)Tb4b4b4{
Te6edf3stateTb4b4b4.Te6edf3connTb4b4b4.Te6edf3setTb4b4b4(Te6edf3sTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sTb4b4b4.Te6edf3state Tff7b72=== Ta5d6ff'idle'Tb4b4b4) Tb4b4b4{
T8b949e// Fully torn down (user-initiated disconnect path).
Te6edf3client Tff7b72= Tff7b72nullTb4b4b4; Te6edf3transport Tff7b72= Tff7b72nullTb4b4b4; Te6edf3legacy Tff7b72= Tff7b72nullTb4b4b4;
Te6edf3clearSessionStateTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3reconnectingTb4b4b4.Te6edf3setTb4b4b4(Tff7b72falseTb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3sTb4b4b4.Te6edf3state Tff7b72=== Ta5d6ff'closed'Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3userInitiatedDisconnect Tff7b72|| Tff7b72!Te6edf3stateTb4b4b4.Te6edf3autoReconnectTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4) Tff7b72|| Tff7b72!Te6edf3transportTb4b4b4) Tb4b4b4{
T8b949e// No reconnect: clear session, drop handles.
Te6edf3client Tff7b72= Tff7b72nullTb4b4b4; Te6edf3transport Tff7b72= Tff7b72nullTb4b4b4; Te6edf3legacy Tff7b72= Tff7b72nullTb4b4b4;
Te6edf3clearSessionStateTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3reconnectingTb4b4b4.Te6edf3setTb4b4b4(Tff7b72falseTb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
T8b949e// Device went away (probably a reboot); start auto-reconnect.
Te6edf3startReconnectTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

Tff7b72async Tff7b72function Te6edf3doConnectTb4b4b4(Tb4b4b4)Tb4b4b4{
Te6edf3userInitiatedDisconnect Tff7b72= Tff7b72falseTb4b4b4;
Te6edf3reconnectTokenTff7b72++Tb4b4b4;
Tff7b72const Te6edf3name Tff7b72= Te6edf3stateTb4b4b4.Te6edf3transportNameTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3lastTransportName Tff7b72= Te6edf3nameTb4b4b4;
Tff7b72try Tb4b4b4{
Te6edf3transport Tff7b72= Te6edf3createTransportTb4b4b4(Te6edf3nameTb4b4b4)Tb4b4b4;
Te6edf3transportTb4b4b4.Te6edf3onStatus Tff7b72= Te6edf3onTransportStatusTb4b4b4;
Te6edf3client Tff7b72= Tff7b72new Te6edf3ProvisioningClientTb4b4b4(Te6edf3transportTb4b4b4)Tb4b4b4;
Te6edf3wireClientTb4b4b4(Te6edf3clientTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3name Tff7b72=== Ta5d6ff'ws'Tb4b4b4) Tff7b72await Te6edf3transportTb4b4b4.Te6edf3connectTb4b4b4(Te6edf3stateTb4b4b4.Te6edf3wsUrlTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72else Tff7b72if Tb4b4b4(Te6edf3name Tff7b72=== Ta5d6ff'rns'Tb4b4b4) Tff7b72await Te6edf3transportTb4b4b4.Te6edf3connectTb4b4b4(Tb4b4b4{
Te6edf3meshchatxUrlTff7b72: Te6edf3stateTb4b4b4.Te6edf3rnsUrlTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3destinationHashTff7b72: Te6edf3stateTb4b4b4.Te6edf3rnsDestHashTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3aspectTff7b72: Te6edf3stateTb4b4b4.Te6edf3rnsAspectTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3autoIdentifyTff7b72: Te6edf3stateTb4b4b4.Te6edf3rnsAutoIdentifyTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72else Tff7b72await Te6edf3transportTb4b4b4.Te6edf3connectTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72await Te6edf3afterConnectTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{
Te6edf3consoleTb4b4b4.Te6edf3errorTb4b4b4(Ta5d6ff'connect failed:'Tb4b4b4, Te6edf3eTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}

Tff7b72async Tff7b72function Te6edf3afterConnectTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72try Tb4b4b4{ Te6edf3stateTb4b4b4.Te6edf3infoTb4b4b4.Te6edf3setTb4b4b4(Tff7b72await Te6edf3clientTb4b4b4.Te6edf3getInfoTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Te6edf3consoleTb4b4b4.Te6edf3errorTb4b4b4(Ta5d6ff'getInfo:'Tb4b4b4, Te6edf3eTb4b4b4)Tb4b4b4; Te6edf3showToastTb4b4b4(Ta5d6ff'Failed to fetch device info: ' Tff7b72+ Te6edf3eTb4b4b4.Te6edf3messageTb4b4b4, Ta5d6ff'err'Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72try Tb4b4b4{
Tff7b72const Te6edf3schema Tff7b72= Tff7b72await Te6edf3clientTb4b4b4.Te6edf3resolveSchemaTb4b4b4(Te6edf3stateTb4b4b4.Te6edf3infoTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3schemaTb4b4b4.Te6edf3setTb4b4b4(Te6edf3schemaTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3schemaTb4b4b4.Te6edf3namespacesTb4b4b4.Te6edf3length Tff7b72> T79c0ff0 Tff7b72&& Te6edf3stateTb4b4b4.Te6edf3activeNsTabTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4) Tff7b72== Tff7b72nullTb4b4b4) Tb4b4b4{
T8b949e// Default to the first ROOT namespace (parentId == 0) — children render
T8b949e// as sub-sections inside their root and aren't selectable on their own.
Tff7b72const Te6edf3firstRoot Tff7b72= Te6edf3schemaTb4b4b4.Te6edf3namespacesTb4b4b4.Te6edf3findTb4b4b4(Te6edf3n Tb4b4b4=> Tff7b72!Tffa657NumberTb4b4b4(Te6edf3nTb4b4b4.Te6edf3parentId Tff7b72|| T79c0ff0Tb4b4b4)Tb4b4b4) Tff7b72|| Te6edf3schemaTb4b4b4.Te6edf3namespacesTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3activeNsTabTb4b4b4.Te6edf3setTb4b4b4(Te6edf3firstRootTb4b4b4.Te6edf3idTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Te6edf3consoleTb4b4b4.Te6edf3errorTb4b4b4(Ta5d6ff'getSchema:'Tb4b4b4, Te6edf3eTb4b4b4)Tb4b4b4; Te6edf3showToastTb4b4b4(Ta5d6ff'Failed to fetch schema: ' Tff7b72+ Te6edf3eTb4b4b4.Te6edf3messageTb4b4b4, Ta5d6ff'err'Tb4b4b4)Tb4b4b4; Tb4b4b4}
T8b949e// Probe whether the device responds to legacy (rnodeconf-style) KISS queries.
T8b949e// CMD_BOARD is a cheap one-byte query: returns 1 byte board model. In TNC
T8b949e// mode the device speaks RNS log over KISS but doesn't service these legacy
T8b949e// commands — the probe times out and we hide the Node Config tab.
Tff7b72if Tb4b4b4(Te6edf3legacyTb4b4b4) Tb4b4b4{
Te6edf3legacyTb4b4b4.Te6edf3queryTb4b4b4(Te6edf3CMD_BOARDTb4b4b4, Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[T79c0ff0x00Tb4b4b4]Tb4b4b4)Tb4b4b4, T79c0ff1500Tb4b4b4)
Tb4b4b4.Te6edf3thenTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Te6edf3stateTb4b4b4.Te6edf3legacySupportedTb4b4b4.Te6edf3setTb4b4b4(Tff7b72trueTb4b4b4)Tb4b4b4)
Tb4b4b4.Tff7b72catchTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Te6edf3stateTb4b4b4.Te6edf3legacySupportedTb4b4b4.Te6edf3setTb4b4b4(Tff7b72falseTb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3stateTb4b4b4.Te6edf3legacySupportedTb4b4b4.Te6edf3setTb4b4b4(Tff7b72falseTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}

Tff7b72async Tff7b72function Te6edf3doDisconnectTb4b4b4(Tb4b4b4)Tb4b4b4{
Te6edf3userInitiatedDisconnect Tff7b72= Tff7b72trueTb4b4b4;
Te6edf3reconnectTokenTff7b72++Tb4b4b4; T8b949e// cancel any in-flight auto-reconnect
Te6edf3stateTb4b4b4.Te6edf3reconnectingTb4b4b4.Te6edf3setTb4b4b4(Tff7b72falseTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3transportTb4b4b4) Tb4b4b4{ Tff7b72try Tb4b4b4{ Tff7b72await Te6edf3transportTb4b4b4.Te6edf3disconnectTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4} Tb4b4b4}
Tb4b4b4}

T8b949e// Poll transport.reconnect() (or a fresh WS) with short backoff so we can catch
T8b949e// early boot logs after a device reset. Driven off a token so doDisconnect or
T8b949e// a fresh doConnect cancels any prior attempt cleanly.
Tff7b72async Tff7b72function Te6edf3startReconnectTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3transport Tff7b72&& Te6edf3lastTransportName Tff7b72!== Ta5d6ff'ws'Tb4b4b4) Tff7b72returnTb4b4b4; T8b949e// nothing to reconnect to
Tff7b72const Te6edf3myToken Tff7b72= Tff7b72++Te6edf3reconnectTokenTb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3reconnectingTb4b4b4.Te6edf3setTb4b4b4(Tff7b72trueTb4b4b4)Tb4b4b4;
T8b949e// Preserve nsState / nodeCfgState across the reconnect window so visible
T8b949e// field values don't flash to field.default while the device is rebooting.
T8b949e// Only invalidate the *Loaded flags — that triggers re-fetch once the device
T8b949e// is back, which then overwrites these maps with fresh data. (Firmware drafts
T8b949e// don't survive reboot, so we still reset the local draft-presence flags.)
Te6edf3stateTb4b4b4.Te6edf3nsLoadedTb4b4b4.Te6edf3setTb4b4b4(Tb4b4b4{Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nsServerErrorsTb4b4b4.Te6edf3setTb4b4b4(Tb4b4b4{Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3firmwareHasDraftTb4b4b4.Te6edf3setTb4b4b4(Tff7b72falseTb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nodeCfgLoadedTb4b4b4.Te6edf3setTb4b4b4(Tb4b4b4{Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nodeCfgHasDraftTb4b4b4.Te6edf3setTb4b4b4(Tff7b72falseTb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nodeCfgEepromTb4b4b4.Te6edf3setTb4b4b4(Tff7b72nullTb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nodeCfgCfgSectorTb4b4b4.Te6edf3setTb4b4b4(Tff7b72nullTb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nodeCfgDeviceInfoTb4b4b4.Te6edf3setTb4b4b4(Tff7b72nullTb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nodeCfgNeedsRebootTb4b4b4.Te6edf3setTb4b4b4(Tff7b72falseTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3deadline Tff7b72= Tffa657DateTb4b4b4.Te6edf3nowTb4b4b4(Tb4b4b4) Tff7b72+ T79c0ff30000Tb4b4b4;
Tff7b72let Te6edf3delay Tff7b72= T79c0ff150Tb4b4b4;
T8b949e// Chrome returns "Failed to execute 'open' on 'SerialPort': Failed to open
T8b949e// serial port." when the OS-level port handle is unrecoverable — usually
T8b949e// after CDC renumeration leaves the saved port reference stale. No amount
T8b949e// of retrying will fix it; only navigator.serial.requestPort() will, and
T8b949e// that needs a user gesture. Bail out after a few consecutive matches so
T8b949e// we surface a "click Connect" prompt instead of spinning for 30s.
Tff7b72let Te6edf3staleOpenFailures Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72let Te6edf3stalePortBailout Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72while Tb4b4b4(Te6edf3myToken Tff7b72=== Te6edf3reconnectToken Tff7b72&& Tffa657DateTb4b4b4.Te6edf3nowTb4b4b4(Tb4b4b4) Tff7b72< Te6edf3deadline Tff7b72&& Tff7b72!Te6edf3userInitiatedDisconnectTb4b4b4) Tb4b4b4{
Tff7b72try Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3lastTransportName Tff7b72=== Ta5d6ff'ws'Tb4b4b4) Tb4b4b4{
T8b949e// WS server-side socket is gone; build a fresh transport+client.
Te6edf3transport Tff7b72= Tff7b72new Te6edf3WebSocketTransportTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3transportTb4b4b4.Te6edf3onStatus Tff7b72= Te6edf3onTransportStatusTb4b4b4;
Te6edf3client Tff7b72= Tff7b72new Te6edf3ProvisioningClientTb4b4b4(Te6edf3transportTb4b4b4)Tb4b4b4;
Te6edf3wireClientTb4b4b4(Te6edf3clientTb4b4b4)Tb4b4b4;
Tff7b72await Te6edf3transportTb4b4b4.Te6edf3connectTb4b4b4(Te6edf3stateTb4b4b4.Te6edf3wsUrlTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3lastTransportName Tff7b72=== Ta5d6ff'rns'Tb4b4b4) Tb4b4b4{
T8b949e// MeshChatX WS is gone; rebuild and re-open the Link.
Te6edf3transport Tff7b72= Tff7b72new Te6edf3RnsTransportTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3transportTb4b4b4.Te6edf3onStatus Tff7b72= Te6edf3onTransportStatusTb4b4b4;
Te6edf3client Tff7b72= Tff7b72new Te6edf3ProvisioningClientTb4b4b4(Te6edf3transportTb4b4b4)Tb4b4b4;
Te6edf3wireClientTb4b4b4(Te6edf3clientTb4b4b4)Tb4b4b4;
Tff7b72await Te6edf3transportTb4b4b4.Te6edf3connectTb4b4b4(Tb4b4b4{
Te6edf3meshchatxUrlTff7b72: Te6edf3stateTb4b4b4.Te6edf3rnsUrlTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3destinationHashTff7b72: Te6edf3stateTb4b4b4.Te6edf3rnsDestHashTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3aspectTff7b72: Te6edf3stateTb4b4b4.Te6edf3rnsAspectTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3autoIdentifyTff7b72: Te6edf3stateTb4b4b4.Te6edf3rnsAutoIdentifyTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72await Te6edf3transportTb4b4b4.Te6edf3reconnectTb4b4b4(Tb4b4b4)Tb4b4b4;
T8b949e// Serial/BLE reuse the same client instance — clear stale waiters and
T8b949e// re-sync the decoder. WS gets a fresh client above, so this is skipped.
Tff7b72if Tb4b4b4(Te6edf3client Tff7b72&& Te6edf3clientTb4b4b4.Te6edf3resetSessionTb4b4b4) Te6edf3clientTb4b4b4.Te6edf3resetSessionTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3legacy Tff7b72&& Te6edf3legacyTb4b4b4.Te6edf3resetSessionTb4b4b4) Te6edf3legacyTb4b4b4.Te6edf3resetSessionTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3staleOpenFailures Tff7b72= T79c0ff0Tb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3myToken Tff7b72!== Te6edf3reconnectTokenTb4b4b4) Tff7b72returnTb4b4b4; T8b949e// cancelled mid-flight

T8b949e// Probe the device with getInfo until it actually responds. On UART
T8b949e// bridges the host-side port reopens in <10ms but the firmware is still
T8b949e// booting; without this we'd declare success instantly and immediately
T8b949e// hit a 5s getInfo timeout. The probe keeps "Reconnecting…" displayed
T8b949e// for the real duration of the device-side reboot.
Tff7b72let Te6edf3info Tff7b72= Tff7b72nullTb4b4b4;
Tff7b72let Te6edf3lastProbeErr Tff7b72= Tff7b72nullTb4b4b4;
Tff7b72while Tb4b4b4(Te6edf3myToken Tff7b72=== Te6edf3reconnectToken Tff7b72&& Tffa657DateTb4b4b4.Te6edf3nowTb4b4b4(Tb4b4b4) Tff7b72< Te6edf3deadline Tff7b72&& Tff7b72!Te6edf3userInitiatedDisconnectTb4b4b4) Tb4b4b4{
Tff7b72try Tb4b4b4{ Te6edf3info Tff7b72= Tff7b72await Te6edf3clientTb4b4b4.Te6edf3getInfoTb4b4b4(T79c0ff800Tb4b4b4)Tb4b4b4; Tff7b72breakTb4b4b4; Tb4b4b4}
Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Te6edf3lastProbeErr Tff7b72= Te6edf3eTb4b4b4; Tff7b72await Tff7b72new Tffa657PromiseTb4b4b4(Te6edf3r Tb4b4b4=> Te6edf3setTimeoutTb4b4b4(Te6edf3rTb4b4b4, T79c0ff200Tb4b4b4)Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3lastProbeErr Tff7b72&& Tff7b72!Te6edf3infoTb4b4b4) Te6edf3consoleTb4b4b4.Te6edf3warnTb4b4b4(Ta5d6ff'reconnect probe last error:'Tb4b4b4, Te6edf3lastProbeErrTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3myToken Tff7b72!== Te6edf3reconnectTokenTb4b4b4) Tff7b72returnTb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3infoTb4b4b4) Tff7b72throw Tff7b72new Tf85149ErrorTb4b4b4(Ta5d6ff'device did not respond after reconnect'Tb4b4b4)Tb4b4b4;

Te6edf3stateTb4b4b4.Te6edf3infoTb4b4b4.Te6edf3setTb4b4b4(Te6edf3infoTb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3reconnectingTb4b4b4.Te6edf3setTb4b4b4(Tff7b72falseTb4b4b4)Tb4b4b4;
Te6edf3showToastTb4b4b4(Ta5d6ff'Reconnected'Tb4b4b4, Ta5d6ff'ok'Tb4b4b4)Tb4b4b4;

T8b949e// Refresh schema. resolveSchema short-circuits via the in-memory cache /
T8b949e// bundled schema if the device's hash is unchanged across the reboot —
T8b949e// and only falls back to a real GetSchema fetch when the schema actually
T8b949e// changed (e.g. firmware upgrade).
Tff7b72try Tb4b4b4{
Tff7b72const Te6edf3schema Tff7b72= Tff7b72await Te6edf3clientTb4b4b4.Te6edf3resolveSchemaTb4b4b4(Te6edf3infoTb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3schemaTb4b4b4.Te6edf3setTb4b4b4(Te6edf3schemaTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3schemaTb4b4b4.Te6edf3namespacesTb4b4b4.Te6edf3length Tff7b72> T79c0ff0 Tff7b72&& Te6edf3stateTb4b4b4.Te6edf3activeNsTabTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4) Tff7b72== Tff7b72nullTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3firstRoot Tff7b72= Te6edf3schemaTb4b4b4.Te6edf3namespacesTb4b4b4.Te6edf3findTb4b4b4(Te6edf3n Tb4b4b4=> Tff7b72!Tffa657NumberTb4b4b4(Te6edf3nTb4b4b4.Te6edf3parentId Tff7b72|| T79c0ff0Tb4b4b4)Tb4b4b4) Tff7b72|| Te6edf3schemaTb4b4b4.Te6edf3namespacesTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3activeNsTabTb4b4b4.Te6edf3setTb4b4b4(Te6edf3firstRootTb4b4b4.Te6edf3idTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{
Te6edf3consoleTb4b4b4.Te6edf3errorTb4b4b4(Ta5d6ff'getSchema after reconnect:'Tb4b4b4, Te6edf3eTb4b4b4)Tb4b4b4;
Te6edf3showToastTb4b4b4(Ta5d6ff'Failed to fetch schema: ' Tff7b72+ Te6edf3eTb4b4b4.Te6edf3messageTb4b4b4, Ta5d6ff'err'Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72const Te6edf3cur Tff7b72= Te6edf3stateTb4b4b4.Te6edf3activeNsTabTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3cur Tff7b72!= Tff7b72nullTb4b4b4) Te6edf3fetchNamespaceIfNeededTb4b4b4(Te6edf3curTb4b4b4)Tb4b4b4;
Tff7b72returnTb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{
T8b949e// Device not back yet — wait and retry with mild backoff.
Tff7b72const Te6edf3msg Tff7b72= Te6edf3e Tff7b72&& Te6edf3eTb4b4b4.Te6edf3message Tff7b72? Te6edf3eTb4b4b4.Te6edf3message Tff7b72: Tffa657StringTb4b4b4(Te6edf3eTb4b4b4)Tb4b4b4;
Te6edf3consoleTb4b4b4.Te6edf3warnTb4b4b4(Ta5d6ff'reconnect attempt failed:'Tb4b4b4, Te6edf3msgTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Ta5d6ff/Failed to open/iTb4b4b4.Te6edf3testTb4b4b4(Te6edf3msgTb4b4b4) Tff7b72&& Te6edf3lastTransportName Tff7b72!== Ta5d6ff'ws'Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72++Te6edf3staleOpenFailures Tff7b72>= T79c0ff5Tb4b4b4) Tb4b4b4{ Te6edf3stalePortBailout Tff7b72= Tff7b72trueTb4b4b4; Tff7b72breakTb4b4b4; Tb4b4b4}
Tb4b4b4}
Tff7b72await Tff7b72new Tffa657PromiseTb4b4b4(Te6edf3r Tb4b4b4=> Te6edf3setTimeoutTb4b4b4(Te6edf3rTb4b4b4, Te6edf3delayTb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3delay Tff7b72= Tffa657MathTb4b4b4.Te6edf3minTb4b4b4(Te6edf3delay Tff7b72+ T79c0ff100Tb4b4b4, T79c0ff1000Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3myToken Tff7b72!== Te6edf3reconnectTokenTb4b4b4) Tff7b72returnTb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3reconnectingTb4b4b4.Te6edf3setTb4b4b4(Tff7b72falseTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3stalePortBailoutTb4b4b4) Tb4b4b4{
Te6edf3showToastTb4b4b4(Ta5d6ff'Serial port handle went stale (device may have renumerated). Click Connect to re-prompt.'Tb4b4b4, Ta5d6ff'warn'Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Tffa657DateTb4b4b4.Te6edf3nowTb4b4b4(Tb4b4b4) Tff7b72>= Te6edf3deadlineTb4b4b4) Tb4b4b4{
Te6edf3showToastTb4b4b4(Ta5d6ff'Auto-reconnect gave up after 30 seconds'Tb4b4b4, Ta5d6ff'warn'Tb4b4b4)Tb4b4b4;
Tb4b4b4}
T8b949e// Treat as fully disconnected.
Te6edf3client Tff7b72= Tff7b72nullTb4b4b4; Te6edf3transport Tff7b72= Tff7b72nullTb4b4b4; Te6edf3legacy Tff7b72= Tff7b72nullTb4b4b4;
Te6edf3clearSessionStateTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3connTb4b4b4.Te6edf3setTb4b4b4(Tb4b4b4{ Te6edf3stateTff7b72: Ta5d6ff'idle' Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72async Tff7b72function Te6edf3fetchNamespaceIfNeededTb4b4b4(Te6edf3nsIdTb4b4b4)Tb4b4b4{
T8b949e// The argument is a ROOT namespace id. Fetches that namespace AND all of its
T8b949e// descendants in two batched getState calls (one for committed, one for
T8b949e// merged-with-draft). Each child is populated into state.nsState alongside
T8b949e// the root so the panel can render them as sub-sections.
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3clientTb4b4b4) Tff7b72returnTb4b4b4;
Tff7b72const Te6edf3schema Tff7b72= Te6edf3stateTb4b4b4.Te6edf3schemaTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3ids Tff7b72= Te6edf3getNsTreeIdsTb4b4b4(Te6edf3schemaTb4b4b4, Te6edf3nsIdTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3idsTb4b4b4.Te6edf3length Tff7b72=== T79c0ff0Tb4b4b4) Te6edf3idsTb4b4b4.Te6edf3pushTb4b4b4(Tffa657NumberTb4b4b4(Te6edf3nsIdTb4b4b4)Tb4b4b4)Tb4b4b4; T8b949e// schema missing → at least try the root
T8b949e// Skip if every id in the tree is already loaded or already loading.
Tff7b72const Te6edf3loaded Tff7b72= Te6edf3stateTb4b4b4.Te6edf3nsLoadedTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3loading Tff7b72= Te6edf3stateTb4b4b4.Te6edf3nsLoadingTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3todo Tff7b72= Te6edf3idsTb4b4b4.Te6edf3filterTb4b4b4(Te6edf3id Tb4b4b4=> Tff7b72!Te6edf3loadedTb4b4b4[Te6edf3idTb4b4b4] Tff7b72&& Tff7b72!Te6edf3loadingTb4b4b4[Te6edf3idTb4b4b4]Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3todoTb4b4b4.Te6edf3length Tff7b72=== T79c0ff0Tb4b4b4) Tff7b72returnTb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nsLoadingTb4b4b4.Te6edf3updateTb4b4b4(Te6edf3s Tb4b4b4=> Tb4b4b4{ Tff7b72for Tb4b4b4(Tff7b72const Te6edf3id Tff7b72of Te6edf3todoTb4b4b4) Te6edf3sTb4b4b4[Te6edf3idTb4b4b4] Tff7b72= Tff7b72trueTb4b4b4; Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72try Tb4b4b4{
Tff7b72const Te6edf3committedAll Tff7b72= Tff7b72await Te6edf3clientTb4b4b4.Te6edf3getStateTb4b4b4(Te6edf3todoTb4b4b4, Tff7b72falseTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3mergedAll Tff7b72= Tff7b72await Te6edf3clientTb4b4b4.Te6edf3getStateTb4b4b4(Te6edf3todoTb4b4b4, Tff7b72trueTb4b4b4)Tb4b4b4;
Tff7b72let Te6edf3firmwareDraftAny Tff7b72= Tff7b72falseTb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nsStateTb4b4b4.Te6edf3updateTb4b4b4(Te6edf3s Tb4b4b4=> Tb4b4b4{
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3id Tff7b72of Te6edf3todoTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3committed Tff7b72= Te6edf3committedAllTb4b4b4[Te6edf3idTb4b4b4] Tff7b72|| Tb4b4b4{Tb4b4b4}Tb4b4b4;
Tff7b72const Te6edf3merged Tff7b72= Te6edf3mergedAllTb4b4b4[Te6edf3idTb4b4b4] Tff7b72|| Tb4b4b4{Tb4b4b4}Tb4b4b4;
T8b949e// FF_READ_ONLY fields (metrics/instrumentation) report live runtime
T8b949e// values via their getter. Two consecutive GetState calls — one for
T8b949e// committed, one for merged — can sample slightly different values
T8b949e// (e.g. current_rssi, channel utilisation), producing a phantom
T8b949e// "draft" diff that's really just live-value drift. Build a set of
T8b949e// read-only fids up front and exclude them from the diff so the
T8b949e// pending-changes count never reflects this drift.
Tff7b72const Te6edf3ns Tff7b72= Te6edf3getNsByIdTb4b4b4(Te6edf3schemaTb4b4b4, Te6edf3idTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3roFids Tff7b72= Tff7b72new Tffa657SetTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3ns Tff7b72&& Tffa657ArrayTb4b4b4.Te6edf3isArrayTb4b4b4(Te6edf3nsTb4b4b4.Te6edf3fieldsTb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3f Tff7b72of Te6edf3nsTb4b4b4.Te6edf3fieldsTb4b4b4) Tff7b72if Tb4b4b4(Tb4b4b4(Te6edf3fTb4b4b4.Te6edf3flagsTff7b72|T79c0ff0Tb4b4b4) Tff7b72& Te6edf3FFTb4b4b4.Te6edf3READ_ONLYTb4b4b4) Te6edf3roFidsTb4b4b4.Te6edf3addTb4b4b4(Tffa657NumberTb4b4b4(Te6edf3fTb4b4b4.Te6edf3idTb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72const Te6edf3draft Tff7b72= Tb4b4b4{Tb4b4b4}Tb4b4b4;
Tff7b72const Te6edf3firmwareDraftFids Tff7b72= Tff7b72new Tffa657SetTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3fid Tff7b72in Te6edf3mergedTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3nfid Tff7b72= Tffa657NumberTb4b4b4(Te6edf3fidTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3roFidsTb4b4b4.Te6edf3hasTb4b4b4(Te6edf3nfidTb4b4b4)Tb4b4b4) Tff7b72continueTb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3valuesEqualTb4b4b4(Te6edf3mergedTb4b4b4[Te6edf3fidTb4b4b4]Tb4b4b4, Te6edf3committedTb4b4b4[Te6edf3fidTb4b4b4]Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3draftTb4b4b4[Te6edf3nfidTb4b4b4] Tff7b72= Te6edf3mergedTb4b4b4[Te6edf3fidTb4b4b4]Tb4b4b4;
Te6edf3firmwareDraftFidsTb4b4b4.Te6edf3addTb4b4b4(Te6edf3nfidTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Te6edf3sTb4b4b4[Te6edf3idTb4b4b4] Tff7b72= Tb4b4b4{ Te6edf3committedTb4b4b4, Te6edf3draftTb4b4b4, Te6edf3firmwareDraftFids Tb4b4b4}Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3firmwareDraftFidsTb4b4b4.Te6edf3size Tff7b72> T79c0ff0Tb4b4b4) Te6edf3firmwareDraftAny Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nsLoadedTb4b4b4.Te6edf3updateTb4b4b4(Te6edf3s Tb4b4b4=> Tb4b4b4{ Tff7b72for Tb4b4b4(Tff7b72const Te6edf3id Tff7b72of Te6edf3todoTb4b4b4) Te6edf3sTb4b4b4[Te6edf3idTb4b4b4] Tff7b72= Tff7b72trueTb4b4b4; Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3firmwareDraftAnyTb4b4b4) Te6edf3stateTb4b4b4.Te6edf3firmwareHasDraftTb4b4b4.Te6edf3setTb4b4b4(Tff7b72trueTb4b4b4)Tb4b4b4;
Te6edf3recomputeHasDraftTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{
Te6edf3consoleTb4b4b4.Te6edf3errorTb4b4b4(Ta5d6ff'getState failed:'Tb4b4b4, Te6edf3eTb4b4b4)Tb4b4b4;
Te6edf3showToastTb4b4b4(Ta5d6ff'Failed to load ' Tff7b72+ Te6edf3nsId Tff7b72+ Ta5d6ff': ' Tff7b72+ Te6edf3eTb4b4b4.Te6edf3messageTb4b4b4, Ta5d6ff'err'Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72finally Tb4b4b4{
Te6edf3stateTb4b4b4.Te6edf3nsLoadingTb4b4b4.Te6edf3updateTb4b4b4(Te6edf3s Tb4b4b4=> Tb4b4b4{ Tff7b72for Tb4b4b4(Tff7b72const Te6edf3id Tff7b72of Te6edf3todoTb4b4b4) Tff7b72delete Te6edf3sTb4b4b4[Te6edf3idTb4b4b4]Tb4b4b4; Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72function Te6edf3valuesEqualTb4b4b4(Te6edf3aTb4b4b4, Te6edf3bTb4b4b4)Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3a Tff7b72== Tff7b72null Tff7b72&& Te6edf3b Tff7b72== Tff7b72nullTb4b4b4) Tff7b72return Tff7b72trueTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3a Tff7b72== Tff7b72null Tff7b72|| Te6edf3b Tff7b72== Tff7b72nullTb4b4b4) Tff7b72return Tff7b72falseTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3a Tff7b72instanceof Tffa657Uint8Array Tff7b72&& Te6edf3b Tff7b72instanceof Tffa657Uint8ArrayTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3aTb4b4b4.Te6edf3length Tff7b72!== Te6edf3bTb4b4b4.Te6edf3lengthTb4b4b4) Tff7b72return Tff7b72falseTb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72let Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< Te6edf3aTb4b4b4.Te6edf3lengthTb4b4b4; Tff7b72++Te6edf3iTb4b4b4) Tff7b72if Tb4b4b4(Te6edf3aTb4b4b4[Te6edf3iTb4b4b4] Tff7b72!== Te6edf3bTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4) Tff7b72return Tff7b72falseTb4b4b4;
Tff7b72return Tff7b72trueTb4b4b4;
Tb4b4b4}
T8b949e// BytesList: array of Uint8Array. Element-wise equality.
Tff7b72if Tb4b4b4(Tffa657ArrayTb4b4b4.Te6edf3isArrayTb4b4b4(Te6edf3aTb4b4b4) Tff7b72&& Tffa657ArrayTb4b4b4.Te6edf3isArrayTb4b4b4(Te6edf3bTb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3aTb4b4b4.Te6edf3length Tff7b72!== Te6edf3bTb4b4b4.Te6edf3lengthTb4b4b4) Tff7b72return Tff7b72falseTb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72let Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< Te6edf3aTb4b4b4.Te6edf3lengthTb4b4b4; Tff7b72++Te6edf3iTb4b4b4) Tff7b72if Tb4b4b4(Tff7b72!Te6edf3valuesEqualTb4b4b4(Te6edf3aTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4, Te6edf3bTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4)Tb4b4b4) Tff7b72return Tff7b72falseTb4b4b4;
Tff7b72return Tff7b72trueTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Tff7b72typeof Te6edf3a Tff7b72=== Ta5d6ff'bigint' Tff7b72|| Tff7b72typeof Te6edf3b Tff7b72=== Ta5d6ff'bigint'Tb4b4b4) Tff7b72return Tffa657BigIntTb4b4b4(Te6edf3aTb4b4b4) Tff7b72=== Tffa657BigIntTb4b4b4(Te6edf3bTb4b4b4)Tb4b4b4;
Tff7b72return Te6edf3a Tff7b72=== Te6edf3bTb4b4b4;
Tb4b4b4}
T8b949e// Context object describing a config store. The Provisioning ("Transport Config")
T8b949e// store and the Node Config store share these helpers but point at different
T8b949e// observables. Callers that pass no ctx default to the Provisioning store —
T8b949e// keeps existing call sites backwards-compatible.
Tff7b72const Te6edf3PROV_CTX Tff7b72= Tb4b4b4{ Te6edf3get Te6edf3stateTb4b4b4(Tb4b4b4)Tb4b4b4{ Tff7b72return Te6edf3stateTb4b4b4.Te6edf3nsStateTb4b4b4; Tb4b4b4}Tb4b4b4, Te6edf3get Te6edf3errorsTb4b4b4(Tb4b4b4)Tb4b4b4{ Tff7b72return Te6edf3stateTb4b4b4.Te6edf3nsServerErrorsTb4b4b4; Tb4b4b4}Tb4b4b4, Te6edf3get Te6edf3hasDraftTb4b4b4(Tb4b4b4)Tb4b4b4{ Tff7b72return Te6edf3stateTb4b4b4.Te6edf3hasDraftTb4b4b4; Tb4b4b4} Tb4b4b4}Tb4b4b4;
Tff7b72const Te6edf3_ctxOr Tff7b72= Tb4b4b4(Te6edf3ctxTb4b4b4) Tb4b4b4=> Te6edf3ctx Tff7b72|| Te6edf3PROV_CTXTb4b4b4;

Tff7b72function Te6edf3getEffectiveValueTb4b4b4(Te6edf3nsIdTb4b4b4, Te6edf3fieldTb4b4b4, Te6edf3ctxTb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3c Tff7b72= Te6edf3_ctxOrTb4b4b4(Te6edf3ctxTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3s Tff7b72= Te6edf3cTb4b4b4.Te6edf3stateTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4[Te6edf3nsIdTb4b4b4]Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3sTb4b4b4) Tff7b72return Te6edf3fieldTb4b4b4.Tff7b72defaultTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3fieldTb4b4b4.Te6edf3id Tff7b72in Te6edf3sTb4b4b4.Te6edf3draftTb4b4b4) Tff7b72return Te6edf3sTb4b4b4.Te6edf3draftTb4b4b4[Te6edf3fieldTb4b4b4.Te6edf3idTb4b4b4]Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3fieldTb4b4b4.Te6edf3id Tff7b72in Te6edf3sTb4b4b4.Te6edf3committedTb4b4b4) Tff7b72return Te6edf3sTb4b4b4.Te6edf3committedTb4b4b4[Te6edf3fieldTb4b4b4.Te6edf3idTb4b4b4]Tb4b4b4;
Tff7b72return Te6edf3fieldTb4b4b4.Tff7b72defaultTb4b4b4;
Tb4b4b4}
Tff7b72function Te6edf3setDraftValueTb4b4b4(Te6edf3nsIdTb4b4b4, Te6edf3fieldTb4b4b4, Te6edf3valueTb4b4b4, Te6edf3ctxTb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3c Tff7b72= Te6edf3_ctxOrTb4b4b4(Te6edf3ctxTb4b4b4)Tb4b4b4;
Te6edf3cTb4b4b4.Te6edf3stateTb4b4b4.Te6edf3updateTb4b4b4(Te6edf3s Tb4b4b4=> Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3sTb4b4b4[Te6edf3nsIdTb4b4b4]Tb4b4b4) Te6edf3sTb4b4b4[Te6edf3nsIdTb4b4b4] Tff7b72= Tb4b4b4{ Te6edf3committedTff7b72: Tb4b4b4{Tb4b4b4}Tb4b4b4, Te6edf3draftTff7b72: Tb4b4b4{Tb4b4b4} Tb4b4b4}Tb4b4b4;
Tff7b72const Te6edf3committed Tff7b72= Te6edf3sTb4b4b4[Te6edf3nsIdTb4b4b4]Tb4b4b4.Te6edf3committedTb4b4b4[Te6edf3fieldTb4b4b4.Te6edf3idTb4b4b4]Tb4b4b4;
Tff7b72const Te6edf3fwSet Tff7b72= Te6edf3sTb4b4b4[Te6edf3nsIdTb4b4b4]Tb4b4b4.Te6edf3firmwareDraftFidsTb4b4b4;
Tff7b72const Te6edf3fwHasIt Tff7b72= Te6edf3fwSet Tff7b72&& Te6edf3fwSetTb4b4b4.Te6edf3has Tff7b72&& Te6edf3fwSetTb4b4b4.Te6edf3hasTb4b4b4(Te6edf3fieldTb4b4b4.Te6edf3idTb4b4b4)Tb4b4b4;
T8b949e// If the user types back to the committed value AND the firmware doesn't
T8b949e// hold a pending draft for this field, drop the local entry — there's
T8b949e// truly nothing to save. But if the firmware *does* have a draft for
T8b949e// this fid (from a previous Save), keep the local entry so Save remains
T8b949e// enabled; clicking Save will re-send the value and the firmware will
T8b949e// dedup it against working() and erase its own draft, bringing the two
T8b949e// sides back in sync.
Tff7b72if Tb4b4b4(Te6edf3valuesEqualTb4b4b4(Te6edf3valueTb4b4b4, Te6edf3committedTb4b4b4) Tff7b72&& Tff7b72!Te6edf3fwHasItTb4b4b4) Tff7b72delete Te6edf3sTb4b4b4[Te6edf3nsIdTb4b4b4]Tb4b4b4.Te6edf3draftTb4b4b4[Te6edf3fieldTb4b4b4.Te6edf3idTb4b4b4]Tb4b4b4;
Tff7b72else Te6edf3sTb4b4b4[Te6edf3nsIdTb4b4b4]Tb4b4b4.Te6edf3draftTb4b4b4[Te6edf3fieldTb4b4b4.Te6edf3idTb4b4b4] Tff7b72= Te6edf3valueTb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3recomputeHasDraftTb4b4b4(Te6edf3ctxTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72function Te6edf3recomputeHasDraftTb4b4b4(Te6edf3ctxTb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3c Tff7b72= Te6edf3_ctxOrTb4b4b4(Te6edf3ctxTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3s Tff7b72= Te6edf3cTb4b4b4.Te6edf3stateTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3nsId Tff7b72in Te6edf3sTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tffa657ObjectTb4b4b4.Te6edf3keysTb4b4b4(Te6edf3sTb4b4b4[Te6edf3nsIdTb4b4b4]Tb4b4b4.Te6edf3draft Tff7b72|| Tb4b4b4{Tb4b4b4}Tb4b4b4)Tb4b4b4.Te6edf3length Tff7b72> T79c0ff0Tb4b4b4) Tb4b4b4{ Te6edf3cTb4b4b4.Te6edf3hasDraftTb4b4b4.Te6edf3setTb4b4b4(Tff7b72trueTb4b4b4)Tb4b4b4; Tff7b72returnTb4b4b4; Tb4b4b4}
Tb4b4b4}
Te6edf3cTb4b4b4.Te6edf3hasDraftTb4b4b4.Te6edf3setTb4b4b4(Tff7b72falseTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72function Te6edf3validateValueTb4b4b4(Te6edf3fieldTb4b4b4, Te6edf3valueTb4b4b4)Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3value Tff7b72== Tff7b72nullTb4b4b4) Tff7b72return Tff7b72nullTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3fieldTb4b4b4.Te6edf3type Tff7b72=== Te6edf3FTTb4b4b4.Te6edf3Int Tff7b72|| Te6edf3fieldTb4b4b4.Te6edf3type Tff7b72=== Te6edf3FTTb4b4b4.Te6edf3EnumTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3n Tff7b72= Tffa657NumberTb4b4b4(Te6edf3valueTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Tffa657NumberTb4b4b4.Tffa657isFiniteTb4b4b4(Te6edf3nTb4b4b4) Tff7b72|| Tffa657MathTb4b4b4.Te6edf3truncTb4b4b4(Te6edf3nTb4b4b4) Tff7b72!== Te6edf3nTb4b4b4) Tff7b72return Ta5d6ff'must be an integer'Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3fieldTb4b4b4.Te6edf3minI Tff7b72!= Tff7b72null Tff7b72&& Te6edf3n Tff7b72< Tffa657NumberTb4b4b4(Te6edf3fieldTb4b4b4.Te6edf3minITb4b4b4)Tb4b4b4) Tff7b72return Ta5d6ff`Ta5d6ffmin Tffd700${Te6edf3fieldTb4b4b4.Te6edf3minITffd700}Ta5d6ff`Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3fieldTb4b4b4.Te6edf3maxI Tff7b72!= Tff7b72null Tff7b72&& Te6edf3n Tff7b72> Tffa657NumberTb4b4b4(Te6edf3fieldTb4b4b4.Te6edf3maxITb4b4b4)Tb4b4b4) Tff7b72return Ta5d6ff`Ta5d6ffmax Tffd700${Te6edf3fieldTb4b4b4.Te6edf3maxITffd700}Ta5d6ff`Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3fieldTb4b4b4.Te6edf3type Tff7b72=== Te6edf3FTTb4b4b4.Te6edf3FloatTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3n Tff7b72= Tffa657NumberTb4b4b4(Te6edf3valueTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Tffa657NumberTb4b4b4.Tffa657isFiniteTb4b4b4(Te6edf3nTb4b4b4)Tb4b4b4) Tff7b72return Ta5d6ff'must be a number'Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3fieldTb4b4b4.Te6edf3minF Tff7b72!= Tff7b72null Tff7b72&& Te6edf3n Tff7b72< Tffa657NumberTb4b4b4(Te6edf3fieldTb4b4b4.Te6edf3minFTb4b4b4)Tb4b4b4) Tff7b72return Ta5d6ff`Ta5d6ffmin Tffd700${Te6edf3fieldTb4b4b4.Te6edf3minFTffd700}Ta5d6ff`Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3fieldTb4b4b4.Te6edf3maxF Tff7b72!= Tff7b72null Tff7b72&& Te6edf3n Tff7b72> Tffa657NumberTb4b4b4(Te6edf3fieldTb4b4b4.Te6edf3maxFTb4b4b4)Tb4b4b4) Tff7b72return Ta5d6ff`Ta5d6ffmax Tffd700${Te6edf3fieldTb4b4b4.Te6edf3maxFTffd700}Ta5d6ff`Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3fieldTb4b4b4.Te6edf3type Tff7b72=== Te6edf3FTTb4b4b4.Tffa657StringTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3fieldTb4b4b4.Te6edf3maxLen Tff7b72!= Tff7b72null Tff7b72&& Tffa657StringTb4b4b4(Te6edf3valueTb4b4b4)Tb4b4b4.Te6edf3length Tff7b72> Tffa657NumberTb4b4b4(Te6edf3fieldTb4b4b4.Te6edf3maxLenTb4b4b4)Tb4b4b4) Tff7b72return Ta5d6ff`Ta5d6ffmax length Tffd700${Te6edf3fieldTb4b4b4.Te6edf3maxLenTffd700}Ta5d6ff`Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3fieldTb4b4b4.Te6edf3type Tff7b72=== Te6edf3FTTb4b4b4.Te6edf3BytesTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3len Tff7b72= Te6edf3value Tff7b72instanceof Tffa657Uint8Array Tff7b72? Te6edf3valueTb4b4b4.Te6edf3length Tff7b72: T79c0ff0Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3fieldTb4b4b4.Te6edf3maxLen Tff7b72!= Tff7b72null Tff7b72&& Te6edf3len Tff7b72> Tffa657NumberTb4b4b4(Te6edf3fieldTb4b4b4.Te6edf3maxLenTb4b4b4)Tb4b4b4) Tff7b72return Ta5d6ff`Ta5d6ffmax length Tffd700${Te6edf3fieldTb4b4b4.Te6edf3maxLenTffd700}Ta5d6ff bytesTa5d6ff`Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3fieldTb4b4b4.Te6edf3type Tff7b72=== Te6edf3FTTb4b4b4.Te6edf3BytesListTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Tffa657ArrayTb4b4b4.Te6edf3isArrayTb4b4b4(Te6edf3valueTb4b4b4)Tb4b4b4) Tff7b72return Ta5d6ff'must be a list'Tb4b4b4;
Tff7b72const Te6edf3max Tff7b72= Te6edf3fieldTb4b4b4.Te6edf3maxCount Tff7b72!= Tff7b72null Tff7b72? Tffa657NumberTb4b4b4(Te6edf3fieldTb4b4b4.Te6edf3maxCountTb4b4b4) Tff7b72: T79c0ff0Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3max Tff7b72> T79c0ff0 Tff7b72&& Te6edf3valueTb4b4b4.Te6edf3length Tff7b72> Te6edf3maxTb4b4b4) Tff7b72return Ta5d6ff`Ta5d6ffmax Tffd700${Te6edf3maxTffd700}Ta5d6ff entriesTa5d6ff`Tb4b4b4;
Tff7b72const Te6edf3sz Tff7b72= Te6edf3fieldTb4b4b4.Te6edf3elementSize Tff7b72!= Tff7b72null Tff7b72? Tffa657NumberTb4b4b4(Te6edf3fieldTb4b4b4.Te6edf3elementSizeTb4b4b4) Tff7b72: T79c0ff0Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72let Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< Te6edf3valueTb4b4b4.Te6edf3lengthTb4b4b4; Tff7b72++Te6edf3iTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3e Tff7b72= Te6edf3valueTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Tb4b4b4(Te6edf3e Tff7b72instanceof Tffa657Uint8ArrayTb4b4b4)Tb4b4b4) Tff7b72return Ta5d6ff`Ta5d6ffentry Tffd700${Te6edf3iTff7b72+T79c0ff1Tffd700}Ta5d6ff: not bytesTa5d6ff`Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sz Tff7b72> T79c0ff0 Tff7b72&& Te6edf3eTb4b4b4.Te6edf3length Tff7b72!== Te6edf3szTb4b4b4) Tff7b72return Ta5d6ff`Ta5d6ffentry Tffd700${Te6edf3iTff7b72+T79c0ff1Tffd700}Ta5d6ff: must be exactly Tffd700${Te6edf3szTffd700}Ta5d6ff bytes (got Tffd700${Te6edf3eTb4b4b4.Te6edf3lengthTffd700}Ta5d6ff)Ta5d6ff`Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72return Tff7b72nullTb4b4b4;
Tb4b4b4}
Tff7b72function Te6edf3nsDraftCountTb4b4b4(Te6edf3nsIdTb4b4b4, Te6edf3ctxTb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3s Tff7b72= Te6edf3_ctxOrTb4b4b4(Te6edf3ctxTb4b4b4)Tb4b4b4.Te6edf3stateTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4[Te6edf3nsIdTb4b4b4]Tb4b4b4;
Tff7b72return Te6edf3s Tff7b72? Tffa657ObjectTb4b4b4.Te6edf3keysTb4b4b4(Te6edf3sTb4b4b4.Te6edf3draft Tff7b72|| Tb4b4b4{Tb4b4b4}Tb4b4b4)Tb4b4b4.Te6edf3length Tff7b72: T79c0ff0Tb4b4b4;
Tb4b4b4}

T8b949e// ===== Namespace tree (schema v2: namespace.parentId, parentId==0 == root) =====
Tff7b72function Te6edf3getNsByIdTb4b4b4(Te6edf3schemaTb4b4b4, Te6edf3nsIdTb4b4b4)Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3schema Tff7b72|| Tff7b72!Tffa657ArrayTb4b4b4.Te6edf3isArrayTb4b4b4(Te6edf3schemaTb4b4b4.Te6edf3namespacesTb4b4b4)Tb4b4b4) Tff7b72return Tff7b72nullTb4b4b4;
Tff7b72return Te6edf3schemaTb4b4b4.Te6edf3namespacesTb4b4b4.Te6edf3findTb4b4b4(Te6edf3n Tb4b4b4=> Tffa657NumberTb4b4b4(Te6edf3nTb4b4b4.Te6edf3idTb4b4b4) Tff7b72=== Tffa657NumberTb4b4b4(Te6edf3nsIdTb4b4b4)Tb4b4b4) Tff7b72|| Tff7b72nullTb4b4b4;
Tb4b4b4}
T8b949e// Direct children of a namespace id (or roots if parentId==0).
Tff7b72function Te6edf3getChildrenOfTb4b4b4(Te6edf3schemaTb4b4b4, Te6edf3parentIdTb4b4b4)Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3schema Tff7b72|| Tff7b72!Tffa657ArrayTb4b4b4.Te6edf3isArrayTb4b4b4(Te6edf3schemaTb4b4b4.Te6edf3namespacesTb4b4b4)Tb4b4b4) Tff7b72return Tb4b4b4[Tb4b4b4]Tb4b4b4;
Tff7b72return Te6edf3schemaTb4b4b4.Te6edf3namespacesTb4b4b4.Te6edf3filterTb4b4b4(Te6edf3n Tb4b4b4=> Tffa657NumberTb4b4b4(Te6edf3nTb4b4b4.Te6edf3parentId Tff7b72|| T79c0ff0Tb4b4b4) Tff7b72=== Tffa657NumberTb4b4b4(Te6edf3parentIdTb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
T8b949e// Depth-first traversal of a namespace and its descendants. Returns ids in
T8b949e// the order: root, child1, child1.grandchild1, ..., child2, child2.gc1, ...
T8b949e// Used for fetching the whole tree in one go and for rendering sub-sections
T8b949e// in a stable order.
Tff7b72function Te6edf3getNsTreeIdsTb4b4b4(Te6edf3schemaTb4b4b4, Te6edf3rootIdTb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3out Tff7b72= Tb4b4b4[Tb4b4b4]Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3schemaTb4b4b4) Tff7b72return Te6edf3outTb4b4b4;
Tff7b72const Te6edf3walk Tff7b72= Tb4b4b4(Te6edf3idTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3ns Tff7b72= Te6edf3getNsByIdTb4b4b4(Te6edf3schemaTb4b4b4, Te6edf3idTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3nsTb4b4b4) Tff7b72returnTb4b4b4;
Te6edf3outTb4b4b4.Te6edf3pushTb4b4b4(Tffa657NumberTb4b4b4(Te6edf3nsTb4b4b4.Te6edf3idTb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3child Tff7b72of Te6edf3getChildrenOfTb4b4b4(Te6edf3schemaTb4b4b4, Te6edf3nsTb4b4b4.Te6edf3idTb4b4b4)Tb4b4b4) Te6edf3walkTb4b4b4(Te6edf3childTb4b4b4.Te6edf3idTb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4;
Te6edf3walkTb4b4b4(Te6edf3rootIdTb4b4b4)Tb4b4b4;
Tff7b72return Te6edf3outTb4b4b4;
Tb4b4b4}
T8b949e// Total drafted-field count across a namespace and all its descendants. Used
T8b949e// for the sidenav "•" indicator on root namespaces.
Tff7b72function Te6edf3nsTreeDraftCountTb4b4b4(Te6edf3schemaTb4b4b4, Te6edf3rootIdTb4b4b4, Te6edf3ctxTb4b4b4)Tb4b4b4{
Tff7b72let Te6edf3n Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3id Tff7b72of Te6edf3getNsTreeIdsTb4b4b4(Te6edf3schemaTb4b4b4, Te6edf3rootIdTb4b4b4)Tb4b4b4) Te6edf3n Tff7b72+= Te6edf3nsDraftCountTb4b4b4(Te6edf3idTb4b4b4, Te6edf3ctxTb4b4b4)Tb4b4b4;
Tff7b72return Te6edf3nTb4b4b4;
Tb4b4b4}

T8b949e// ===== Toasts =====
Tff7b72function Te6edf3showToastTb4b4b4(Te6edf3textTb4b4b4, Te6edf3kindTb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3host Tff7b72= Tffa657documentTb4b4b4.Te6edf3getElementByIdTb4b4b4(Ta5d6ff'toasts'Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3t Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'toast ' Tff7b72+ Tb4b4b4(Te6edf3kind Tff7b72|| Ta5d6ff'info'Tb4b4b4) Tb4b4b4}Tb4b4b4, Te6edf3textTb4b4b4)Tb4b4b4;
Te6edf3hostTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3tTb4b4b4)Tb4b4b4;
Te6edf3requestAnimationFrameTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Te6edf3tTb4b4b4.Te6edf3classListTb4b4b4.Te6edf3addTb4b4b4(Ta5d6ff'show'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3setTimeoutTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Te6edf3tTb4b4b4.Te6edf3classListTb4b4b4.Te6edf3removeTb4b4b4(Ta5d6ff'show'Tb4b4b4)Tb4b4b4;
Te6edf3setTimeoutTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{ Tff7b72if Tb4b4b4(Te6edf3tTb4b4b4.Te6edf3parentNodeTb4b4b4) Te6edf3tTb4b4b4.Te6edf3parentNodeTb4b4b4.Te6edf3removeChildTb4b4b4(Te6edf3tTb4b4b4)Tb4b4b4; Tb4b4b4}Tb4b4b4, T79c0ff250Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4, T79c0ff3000Tb4b4b4)Tb4b4b4;
Tb4b4b4}

T8b949e// ===== Operations =====
Tff7b72async Tff7b72function Te6edf3saveNamespaceTb4b4b4(Te6edf3nsIdTb4b4b4)Tb4b4b4{
T8b949e// Save the namespace AND all its descendants in a single SetState request.
T8b949e// Drafts from any sub-section in the tree contribute to the payload.
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3clientTb4b4b4) Tff7b72returnTb4b4b4;
Tff7b72const Te6edf3schema Tff7b72= Te6edf3stateTb4b4b4.Te6edf3schemaTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3schemaTb4b4b4) Tff7b72returnTb4b4b4;
Tff7b72const Te6edf3treeIds Tff7b72= Te6edf3getNsTreeIdsTb4b4b4(Te6edf3schemaTb4b4b4, Te6edf3nsIdTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3stateMap Tff7b72= Tb4b4b4{Tb4b4b4}Tb4b4b4;
Tff7b72let Te6edf3totalDraftFields Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3id Tff7b72of Te6edf3treeIdsTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3nsObj Tff7b72= Te6edf3stateTb4b4b4.Te6edf3nsStateTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4[Te6edf3idTb4b4b4]Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3nsObjTb4b4b4) Tff7b72continueTb4b4b4;
Tff7b72const Te6edf3ns Tff7b72= Te6edf3getNsByIdTb4b4b4(Te6edf3schemaTb4b4b4, Te6edf3idTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3nsTb4b4b4) Tff7b72continueTb4b4b4;
Tff7b72const Te6edf3fields Tff7b72= Tb4b4b4{Tb4b4b4}Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3fidStr Tff7b72in Te6edf3nsObjTb4b4b4.Te6edf3draftTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3fid Tff7b72= Tffa657NumberTb4b4b4(Te6edf3fidStrTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3f Tff7b72= Te6edf3nsTb4b4b4.Te6edf3fieldsTb4b4b4.Te6edf3findTb4b4b4(Te6edf3ff Tb4b4b4=> Te6edf3ffTb4b4b4.Te6edf3id Tff7b72=== Te6edf3fidTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3fTb4b4b4) Tff7b72continueTb4b4b4;
Te6edf3fieldsTb4b4b4[Te6edf3fidTb4b4b4] Tff7b72= Tb4b4b4{ Te6edf3typeTff7b72: Te6edf3fTb4b4b4.Te6edf3typeTb4b4b4, Te6edf3valueTff7b72: Te6edf3nsObjTb4b4b4.Te6edf3draftTb4b4b4[Te6edf3fidTb4b4b4] Tb4b4b4}Tb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Tffa657ObjectTb4b4b4.Te6edf3keysTb4b4b4(Te6edf3fieldsTb4b4b4)Tb4b4b4.Te6edf3length Tff7b72> T79c0ff0Tb4b4b4) Tb4b4b4{ Te6edf3stateMapTb4b4b4[Te6edf3idTb4b4b4] Tff7b72= Te6edf3fieldsTb4b4b4; Te6edf3totalDraftFields Tff7b72+= Tffa657ObjectTb4b4b4.Te6edf3keysTb4b4b4(Te6edf3fieldsTb4b4b4)Tb4b4b4.Te6edf3lengthTb4b4b4; Tb4b4b4}
Tb4b4b4}
Tff7b72if Tb4b4b4(Tffa657ObjectTb4b4b4.Te6edf3keysTb4b4b4(Te6edf3stateMapTb4b4b4)Tb4b4b4.Te6edf3length Tff7b72=== T79c0ff0Tb4b4b4) Tff7b72returnTb4b4b4;
Tff7b72try Tb4b4b4{
Tff7b72const Te6edf3r Tff7b72= Tff7b72await Te6edf3clientTb4b4b4.Te6edf3setStateTb4b4b4(Te6edf3stateMapTb4b4b4)Tb4b4b4;
T8b949e// Spread server-side field errors back to their owning namespace.
Tff7b72const Te6edf3perNs Tff7b72= Tb4b4b4{Tb4b4b4}Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3fe Tff7b72of Te6edf3rTb4b4b4.Te6edf3fieldErrorsTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3perNsTb4b4b4[Te6edf3feTb4b4b4.Te6edf3nsTb4b4b4]Tb4b4b4) Te6edf3perNsTb4b4b4[Te6edf3feTb4b4b4.Te6edf3nsTb4b4b4] Tff7b72= Tb4b4b4{Tb4b4b4}Tb4b4b4;
Te6edf3perNsTb4b4b4[Te6edf3feTb4b4b4.Te6edf3nsTb4b4b4]Tb4b4b4[Te6edf3feTb4b4b4.Te6edf3fieldTb4b4b4] Tff7b72= Te6edf3feTb4b4b4.Te6edf3codeNameTb4b4b4;
Tb4b4b4}
Te6edf3stateTb4b4b4.Te6edf3nsServerErrorsTb4b4b4.Te6edf3updateTb4b4b4(Te6edf3s Tb4b4b4=> Tb4b4b4{ Tff7b72for Tb4b4b4(Tff7b72const Te6edf3id Tff7b72of Te6edf3treeIdsTb4b4b4) Te6edf3sTb4b4b4[Te6edf3idTb4b4b4] Tff7b72= Te6edf3perNsTb4b4b4[Te6edf3idTb4b4b4] Tff7b72|| Tb4b4b4{Tb4b4b4}Tb4b4b4; Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nsLoadedTb4b4b4.Te6edf3updateTb4b4b4(Te6edf3s Tb4b4b4=> Tb4b4b4{ Tff7b72for Tb4b4b4(Tff7b72const Te6edf3id Tff7b72of Te6edf3treeIdsTb4b4b4) Tff7b72delete Te6edf3sTb4b4b4[Te6edf3idTb4b4b4]Tb4b4b4; Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3rTb4b4b4.Te6edf3applied Tff7b72> T79c0ff0Tb4b4b4) Te6edf3stateTb4b4b4.Te6edf3firmwareHasDraftTb4b4b4.Te6edf3setTb4b4b4(Tff7b72trueTb4b4b4)Tb4b4b4;
Tff7b72await Te6edf3fetchNamespaceIfNeededTb4b4b4(Te6edf3nsIdTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3ns Tff7b72= Te6edf3getNsByIdTb4b4b4(Te6edf3schemaTb4b4b4, Te6edf3nsIdTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3label Tff7b72= Te6edf3ns Tff7b72? Te6edf3nsTb4b4b4.Te6edf3name Tff7b72: Tffa657StringTb4b4b4(Te6edf3nsIdTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3rTb4b4b4.Te6edf3fieldErrorsTb4b4b4.Te6edf3length Tff7b72=== T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3showToastTb4b4b4(Ta5d6ff`Ta5d6ffSaved Tffd700${Te6edf3rTb4b4b4.Te6edf3appliedTffd700}Ta5d6ff fieldTffd700${Te6edf3rTb4b4b4.Te6edf3applied Tff7b72!== T79c0ff1 Tff7b72? Ta5d6ff's' Tff7b72: Ta5d6ff''Tffd700}Ta5d6ff to "Tffd700${Te6edf3labelTffd700}Ta5d6ff"Ta5d6ff`Tb4b4b4, Ta5d6ff'ok'Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3showToastTb4b4b4(Ta5d6ff`Ta5d6ffSaved with Tffd700${Te6edf3rTb4b4b4.Te6edf3fieldErrorsTb4b4b4.Te6edf3lengthTffd700}Ta5d6ff errorTffd700${Te6edf3rTb4b4b4.Te6edf3fieldErrorsTb4b4b4.Te6edf3length Tff7b72!== T79c0ff1 Tff7b72? Ta5d6ff's' Tff7b72: Ta5d6ff''Tffd700}Ta5d6ff`Tb4b4b4, Ta5d6ff'warn'Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{
Te6edf3showToastTb4b4b4(Ta5d6ff'Save failed: ' Tff7b72+ Te6edf3eTb4b4b4.Te6edf3messageTb4b4b4, Ta5d6ff'err'Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72async Tff7b72function Te6edf3revertNamespaceTb4b4b4(Te6edf3nsIdTb4b4b4)Tb4b4b4{
T8b949e// Revert: discard firmware-side drafts AND clear local drafts for this
T8b949e// namespace and all its descendants, then re-fetch the tree.
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3clientTb4b4b4) Tff7b72returnTb4b4b4;
Tff7b72const Te6edf3schema Tff7b72= Te6edf3stateTb4b4b4.Te6edf3schemaTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3treeIds Tff7b72= Te6edf3schema Tff7b72? Te6edf3getNsTreeIdsTb4b4b4(Te6edf3schemaTb4b4b4, Te6edf3nsIdTb4b4b4) Tff7b72: Tb4b4b4[Tffa657NumberTb4b4b4(Te6edf3nsIdTb4b4b4)Tb4b4b4]Tb4b4b4;
Tff7b72try Tb4b4b4{
Tff7b72await Te6edf3clientTb4b4b4.Te6edf3discardTb4b4b4(Te6edf3treeIdsTb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nsServerErrorsTb4b4b4.Te6edf3updateTb4b4b4(Te6edf3s Tb4b4b4=> Tb4b4b4{ Tff7b72for Tb4b4b4(Tff7b72const Te6edf3id Tff7b72of Te6edf3treeIdsTb4b4b4) Tff7b72delete Te6edf3sTb4b4b4[Te6edf3idTb4b4b4]Tb4b4b4; Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nsLoadedTb4b4b4.Te6edf3updateTb4b4b4(Te6edf3s Tb4b4b4=> Tb4b4b4{ Tff7b72for Tb4b4b4(Tff7b72const Te6edf3id Tff7b72of Te6edf3treeIdsTb4b4b4) Tff7b72delete Te6edf3sTb4b4b4[Te6edf3idTb4b4b4]Tb4b4b4; Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72await Te6edf3fetchNamespaceIfNeededTb4b4b4(Te6edf3nsIdTb4b4b4)Tb4b4b4;
Te6edf3showToastTb4b4b4(Ta5d6ff'Reverted draft changes'Tb4b4b4, Ta5d6ff'ok'Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{
Te6edf3showToastTb4b4b4(Ta5d6ff'Revert failed: ' Tff7b72+ Te6edf3eTb4b4b4.Te6edf3messageTb4b4b4, Ta5d6ff'err'Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72async Tff7b72function Te6edf3refreshNamespaceTb4b4b4(Te6edf3nsIdTb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3schema Tff7b72= Te6edf3stateTb4b4b4.Te6edf3schemaTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3treeIds Tff7b72= Te6edf3schema Tff7b72? Te6edf3getNsTreeIdsTb4b4b4(Te6edf3schemaTb4b4b4, Te6edf3nsIdTb4b4b4) Tff7b72: Tb4b4b4[Tffa657NumberTb4b4b4(Te6edf3nsIdTb4b4b4)Tb4b4b4]Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nsLoadedTb4b4b4.Te6edf3updateTb4b4b4(Te6edf3s Tb4b4b4=> Tb4b4b4{ Tff7b72for Tb4b4b4(Tff7b72const Te6edf3id Tff7b72of Te6edf3treeIdsTb4b4b4) Tff7b72delete Te6edf3sTb4b4b4[Te6edf3idTb4b4b4]Tb4b4b4; Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72await Te6edf3fetchNamespaceIfNeededTb4b4b4(Te6edf3nsIdTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72async Tff7b72function Te6edf3commitAllTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3clientTb4b4b4) Tff7b72returnTb4b4b4;
Tff7b72try Tb4b4b4{
Tff7b72const Te6edf3r Tff7b72= Tff7b72await Te6edf3clientTb4b4b4.Te6edf3commitTb4b4b4(Tff7b72nullTb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nsServerErrorsTb4b4b4.Te6edf3setTb4b4b4(Tb4b4b4{Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nsLoadedTb4b4b4.Te6edf3setTb4b4b4(Tb4b4b4{Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nsStateTb4b4b4.Te6edf3setTb4b4b4(Tb4b4b4{Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3recomputeHasDraftTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3firmwareHasDraftTb4b4b4.Te6edf3setTb4b4b4(Tff7b72falseTb4b4b4)Tb4b4b4;
T8b949e// Banner is derived from state.info.needsReboot; re-fetching info updates it.
Tff7b72try Tb4b4b4{ Te6edf3stateTb4b4b4.Te6edf3infoTb4b4b4.Te6edf3setTb4b4b4(Tff7b72await Te6edf3clientTb4b4b4.Te6edf3getInfoTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4}
Tff7b72const Te6edf3cur Tff7b72= Te6edf3stateTb4b4b4.Te6edf3activeNsTabTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3cur Tff7b72!= Tff7b72nullTb4b4b4) Tff7b72await Te6edf3fetchNamespaceIfNeededTb4b4b4(Te6edf3curTb4b4b4)Tb4b4b4;
Te6edf3showToastTb4b4b4(Ta5d6ff`Ta5d6ffCommitted Tffd700${Te6edf3rTb4b4b4.Te6edf3appliedTffd700}Ta5d6ff changeTffd700${Te6edf3rTb4b4b4.Te6edf3applied Tff7b72!== T79c0ff1 Tff7b72? Ta5d6ff's' Tff7b72: Ta5d6ff''Tffd700}Ta5d6ff` Tff7b72+ Tb4b4b4(Te6edf3rTb4b4b4.Te6edf3needsReboot Tff7b72? Ta5d6ff' — reboot recommended' Tff7b72: Ta5d6ff''Tb4b4b4)Tb4b4b4, Te6edf3rTb4b4b4.Te6edf3needsReboot Tff7b72? Ta5d6ff'warn' Tff7b72: Ta5d6ff'ok'Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{
Te6edf3showToastTb4b4b4(Ta5d6ff'Commit failed: ' Tff7b72+ Te6edf3eTb4b4b4.Te6edf3messageTb4b4b4, Ta5d6ff'err'Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72async Tff7b72function Te6edf3discardAllTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3clientTb4b4b4) Tff7b72returnTb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3confirmTb4b4b4(Ta5d6ff'Discard all pending changes on the device?'Tb4b4b4)Tb4b4b4) Tff7b72returnTb4b4b4;
Tff7b72try Tb4b4b4{
Tff7b72const Te6edf3r Tff7b72= Tff7b72await Te6edf3clientTb4b4b4.Te6edf3discardTb4b4b4(Tff7b72nullTb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nsServerErrorsTb4b4b4.Te6edf3setTb4b4b4(Tb4b4b4{Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nsLoadedTb4b4b4.Te6edf3setTb4b4b4(Tb4b4b4{Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nsStateTb4b4b4.Te6edf3setTb4b4b4(Tb4b4b4{Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3recomputeHasDraftTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3firmwareHasDraftTb4b4b4.Te6edf3setTb4b4b4(Tff7b72falseTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3cur Tff7b72= Te6edf3stateTb4b4b4.Te6edf3activeNsTabTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3cur Tff7b72!= Tff7b72nullTb4b4b4) Tff7b72await Te6edf3fetchNamespaceIfNeededTb4b4b4(Te6edf3curTb4b4b4)Tb4b4b4;
Te6edf3showToastTb4b4b4(Ta5d6ff`Ta5d6ffDiscarded Tffd700${Te6edf3rTb4b4b4.Te6edf3appliedTffd700}Ta5d6ff pending changeTffd700${Te6edf3rTb4b4b4.Te6edf3applied Tff7b72!== T79c0ff1 Tff7b72? Ta5d6ff's' Tff7b72: Ta5d6ff''Tffd700}Ta5d6ff`Tb4b4b4, Ta5d6ff'ok'Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{
Te6edf3showToastTb4b4b4(Ta5d6ff'Discard failed: ' Tff7b72+ Te6edf3eTb4b4b4.Te6edf3messageTb4b4b4, Ta5d6ff'err'Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72async Tff7b72function Te6edf3rebootTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3clientTb4b4b4) Tff7b72returnTb4b4b4;
Tff7b72const Te6edf3auto Tff7b72= Te6edf3stateTb4b4b4.Te6edf3autoReconnectTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3msg Tff7b72= Te6edf3auto
Tff7b72? Ta5d6ff'Reboot the device now? The console will automatically reconnect.'
Tff7b72: Ta5d6ff'Reboot the device now? You will be disconnected.'Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3confirmTb4b4b4(Te6edf3msgTb4b4b4)Tb4b4b4) Tff7b72returnTb4b4b4;
Tff7b72try Tb4b4b4{
T8b949e// Prefer the first-class Provisioning OP.Reboot — works over any
T8b949e// transport, including RNS where legacy KISS CMD_RESET is filtered.
T8b949e// UnknownOp (code 2) means the device's microReticulum is older than
T8b949e// OP.Reboot; fall back to the legacy KISS path.
Tff7b72try Tb4b4b4{
Tff7b72await Te6edf3clientTb4b4b4.Te6edf3requestRebootTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3e Tff7b72&& Tffa657NumberTb4b4b4(Te6edf3eTb4b4b4.Te6edf3codeTb4b4b4) Tff7b72=== T79c0ff2Tb4b4b4) Tff7b72await Te6edf3clientTb4b4b4.Te6edf3rebootTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72else Tff7b72throw Te6edf3eTb4b4b4;
Tb4b4b4}
T8b949e// Reflect the imminent disconnect immediately, AND force-close the transport.
T8b949e// The force-close matters on UART-to-USB bridges (CP2102, CH340, etc) where
T8b949e// the host's serial connection survives the ESP32 reset — without it, the
T8b949e// read loop never observes a disconnect, 'closed' never fires, startReconnect
T8b949e// never runs, and the UI is stuck in "Reconnecting…" forever. On RNS it
T8b949e// also fires rns.link.close so MeshChatX evicts its cached Link.
Tff7b72if Tb4b4b4(Te6edf3autoTb4b4b4) Te6edf3stateTb4b4b4.Te6edf3reconnectingTb4b4b4.Te6edf3setTb4b4b4(Tff7b72trueTb4b4b4)Tb4b4b4;
Te6edf3showToastTb4b4b4(Te6edf3auto
Tff7b72? Ta5d6ff'Reboot command sent — reconnecting…'
Tff7b72: Ta5d6ff'Reboot command sent — device is restarting'Tb4b4b4, Ta5d6ff'ok'Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3transport Tff7b72&& Te6edf3transportTb4b4b4.Te6edf3forceCloseTb4b4b4) Tb4b4b4{
Tff7b72try Tb4b4b4{ Tff7b72await Te6edf3transportTb4b4b4.Te6edf3forceCloseTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4}
Tb4b4b4}
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{
Te6edf3showToastTb4b4b4(Ta5d6ff'Reboot failed: ' Tff7b72+ Te6edf3eTb4b4b4.Te6edf3messageTb4b4b4, Ta5d6ff'err'Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72async Tff7b72function Te6edf3factoryResetTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3clientTb4b4b4) Tff7b72returnTb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3confirmTb4b4b4(Ta5d6ff'Factory-reset all namespaces? This cannot be undone.'Tb4b4b4)Tb4b4b4) Tff7b72returnTb4b4b4;
Tff7b72try Tb4b4b4{
Tff7b72const Te6edf3r Tff7b72= Tff7b72await Te6edf3clientTb4b4b4.Te6edf3factoryResetTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nsLoadedTb4b4b4.Te6edf3setTb4b4b4(Tb4b4b4{Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nsStateTb4b4b4.Te6edf3setTb4b4b4(Tb4b4b4{Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nsServerErrorsTb4b4b4.Te6edf3setTb4b4b4(Tb4b4b4{Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3recomputeHasDraftTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3firmwareHasDraftTb4b4b4.Te6edf3setTb4b4b4(Tff7b72falseTb4b4b4)Tb4b4b4;
T8b949e// Banner is derived from state.info.needsReboot; refresh to pick up the change.
Tff7b72try Tb4b4b4{ Te6edf3stateTb4b4b4.Te6edf3infoTb4b4b4.Te6edf3setTb4b4b4(Tff7b72await Te6edf3clientTb4b4b4.Te6edf3getInfoTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4}
Te6edf3showToastTb4b4b4(Ta5d6ff'Factory reset complete' Tff7b72+ Tb4b4b4(Te6edf3rTb4b4b4.Te6edf3needsReboot Tff7b72? Ta5d6ff' — reboot recommended' Tff7b72: Ta5d6ff''Tb4b4b4)Tb4b4b4, Te6edf3rTb4b4b4.Te6edf3needsReboot Tff7b72? Ta5d6ff'warn' Tff7b72: Ta5d6ff'ok'Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{
Te6edf3showToastTb4b4b4(Ta5d6ff'Factory reset failed: ' Tff7b72+ Te6edf3eTb4b4b4.Te6edf3messageTb4b4b4, Ta5d6ff'err'Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}

T8b949e// ===== Section-based rendering =====
Tff7b72const Te6edf3slots Tff7b72= Tb4b4b4{
Te6edf3topbarTff7b72: Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4)Tb4b4b4,
Te6edf3tabbarTff7b72: Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4)Tb4b4b4,
Te6edf3rebootbannerTff7b72: Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4)Tb4b4b4,
Te6edf3bodyTff7b72: Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'body' Tb4b4b4}Tb4b4b4)Tb4b4b4,
Te6edf3bottombarTff7b72: Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4)Tb4b4b4,
Tb4b4b4}Tb4b4b4;
Tff7b72const Te6edf3app Tff7b72= Tffa657documentTb4b4b4.Te6edf3getElementByIdTb4b4b4(Ta5d6ff'app'Tb4b4b4)Tb4b4b4;
Te6edf3appTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3slotsTb4b4b4.Te6edf3topbarTb4b4b4)Tb4b4b4;
Te6edf3appTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3slotsTb4b4b4.Te6edf3tabbarTb4b4b4)Tb4b4b4;
Te6edf3appTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3slotsTb4b4b4.Te6edf3rebootbannerTb4b4b4)Tb4b4b4;
Te6edf3appTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3slotsTb4b4b4.Te6edf3bodyTb4b4b4)Tb4b4b4;
Te6edf3appTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3slotsTb4b4b4.Te6edf3bottombarTb4b4b4)Tb4b4b4;

T8b949e// Global reboot banner — lives outside the tab body so it stays visible on
T8b949e// every tab, not just Status. Shown when EITHER the Provisioning subsystem
T8b949e// has staged reboot-required changes (info.needsReboot) OR a Node Config
T8b949e// save touched a reboot-required section (state.nodeCfgNeedsReboot).
T8b949e// Cleared on reboot.
Tff7b72function Te6edf3buildRebootBannerTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3banner Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'notice'Tb4b4b4, Te6edf3styleTff7b72: Tb4b4b4{
Te6edf3displayTff7b72: Ta5d6ff'none'Tb4b4b4, Te6edf3alignItemsTff7b72: Ta5d6ff'center'Tb4b4b4, Te6edf3gapTff7b72: Ta5d6ff'12px'Tb4b4b4,
Te6edf3marginTff7b72: Ta5d6ff'8px 12px 0'Tb4b4b4, Te6edf3borderRadiusTff7b72: Ta5d6ff'4px'Tb4b4b4,
Tb4b4b4} Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3msg Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'span'Tb4b4b4, Tb4b4b4{ Te6edf3styleTff7b72: Tb4b4b4{ Te6edf3flexTff7b72: Ta5d6ff'1' Tb4b4b4} Tb4b4b4}Tb4b4b4, Ta5d6ff'Reboot recommended to apply committed changes.'Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3btn Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'button'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'primary'Tb4b4b4, Te6edf3onclickTff7b72: Te6edf3reboot Tb4b4b4}Tb4b4b4, Ta5d6ff'Reboot now'Tb4b4b4)Tb4b4b4;
Te6edf3bannerTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3msgTb4b4b4)Tb4b4b4;
Te6edf3bannerTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3btnTb4b4b4)Tb4b4b4;
Tff7b72function Te6edf3updateTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3info Tff7b72= Te6edf3stateTb4b4b4.Te6edf3infoTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3connected Tff7b72= Te6edf3stateTb4b4b4.Te6edf3connTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3state Tff7b72=== Ta5d6ff'connected'Tb4b4b4;
Tff7b72const Te6edf3show Tff7b72= Tb4b4b4(Tb4b4b4(Te6edf3info Tff7b72&& Te6edf3infoTb4b4b4.Te6edf3needsRebootTb4b4b4) Tff7b72|| Te6edf3stateTb4b4b4.Te6edf3nodeCfgNeedsRebootTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3bannerTb4b4b4.Te6edf3styleTb4b4b4.Te6edf3display Tff7b72= Te6edf3show Tff7b72? Ta5d6ff'flex' Tff7b72: Ta5d6ff'none'Tb4b4b4;
Te6edf3btnTb4b4b4.Te6edf3disabled Tff7b72= Tff7b72!Te6edf3connectedTb4b4b4;
Tb4b4b4}
Te6edf3stateTb4b4b4.Te6edf3infoTb4b4b4.Te6edf3subscribeTb4b4b4(Te6edf3updateTb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nodeCfgNeedsRebootTb4b4b4.Te6edf3subscribeTb4b4b4(Te6edf3updateTb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3connTb4b4b4.Te6edf3subscribeTb4b4b4(Te6edf3updateTb4b4b4)Tb4b4b4;
Te6edf3updateTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72return Te6edf3bannerTb4b4b4;
Tb4b4b4}
Te6edf3slotsTb4b4b4.Te6edf3rebootbannerTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3buildRebootBannerTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;

T8b949e// Cleanup callbacks for the body's currently-mounted tab. Run before building a new
T8b949e// tab so the new tab's builder can push its own cleanups into the (now empty) list.
T8b949e// Critical: take a *build function*, not an already-built node. Building the node
T8b949e// before clearing cleanups would tear down the new tab's subscriptions immediately.
Tff7b72let Te6edf3bodyCleanups Tff7b72= Tb4b4b4[Tb4b4b4]Tb4b4b4;
Tff7b72let Te6edf3bodyKey Tff7b72= Tff7b72nullTb4b4b4;
Tff7b72function Te6edf3setBodyTb4b4b4(Te6edf3keyTb4b4b4, Te6edf3buildFnTb4b4b4)Tb4b4b4{
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3fn Tff7b72of Te6edf3bodyCleanupsTb4b4b4) Tb4b4b4{ Tff7b72try Tb4b4b4{ Te6edf3fnTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4} Tb4b4b4}
Te6edf3bodyCleanups Tff7b72= Tb4b4b4[Tb4b4b4]Tb4b4b4;
Tff7b72const Te6edf3node Tff7b72= Te6edf3buildFnTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3slotsTb4b4b4.Te6edf3bodyTb4b4b4.Te6edf3innerHTML Tff7b72= Ta5d6ff''Tb4b4b4;
Te6edf3slotsTb4b4b4.Te6edf3bodyTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3nodeTb4b4b4)Tb4b4b4;
Te6edf3bodyKey Tff7b72= Te6edf3keyTb4b4b4;
Tb4b4b4}

T8b949e// ----- Top bar (in place) -----
Tff7b72function Te6edf3buildTopBarTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3root Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'topbar' Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3sel Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'select'Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3wsHost Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'span'Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3wsInput Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'input'Tb4b4b4, Tb4b4b4{ Te6edf3typeTff7b72: Ta5d6ff'text'Tb4b4b4, Te6edf3placeholderTff7b72: Ta5d6ff'ws://host:port'Tb4b4b4, Te6edf3styleTff7b72: Tb4b4b4{ Te6edf3widthTff7b72: Ta5d6ff'220px' Tb4b4b4} Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3wsInputTb4b4b4.Te6edf3value Tff7b72= Te6edf3stateTb4b4b4.Te6edf3wsUrlTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3wsInputTb4b4b4.Te6edf3oninput Tff7b72= Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4=> Te6edf3stateTb4b4b4.Te6edf3wsUrlTb4b4b4.Te6edf3setTb4b4b4(Te6edf3eTb4b4b4.Te6edf3targetTb4b4b4.Te6edf3valueTb4b4b4)Tb4b4b4;
T8b949e// Mount once; toggle visibility in update() so typing doesn't detach the
T8b949e// focused input (which would drop focus on every keystroke).
Te6edf3wsHostTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3wsInputTb4b4b4)Tb4b4b4;
T8b949e// RNS-over-MeshChatX config: WS URL + destination hash + aspect + auto-identify.
Tff7b72const Te6edf3rnsHost Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'span'Tb4b4b4, Tb4b4b4{ Te6edf3styleTff7b72: Tb4b4b4{ Te6edf3displayTff7b72: Ta5d6ff'inline-flex'Tb4b4b4, Te6edf3gapTff7b72: Ta5d6ff'4px'Tb4b4b4, Te6edf3alignItemsTff7b72: Ta5d6ff'center' Tb4b4b4} Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3rnsUrlInput Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'input'Tb4b4b4, Tb4b4b4{ Te6edf3typeTff7b72: Ta5d6ff'text'Tb4b4b4, Te6edf3placeholderTff7b72: Ta5d6ff'ws://host:port/ws'Tb4b4b4, Te6edf3styleTff7b72: Tb4b4b4{ Te6edf3widthTff7b72: Ta5d6ff'200px' Tb4b4b4}Tb4b4b4, Te6edf3titleTff7b72: Ta5d6ff'MeshChatX WebSocket URL' Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3rnsUrlInputTb4b4b4.Te6edf3value Tff7b72= Te6edf3stateTb4b4b4.Te6edf3rnsUrlTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3rnsUrlInputTb4b4b4.Te6edf3oninput Tff7b72= Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4=> Te6edf3stateTb4b4b4.Te6edf3rnsUrlTb4b4b4.Te6edf3setTb4b4b4(Te6edf3eTb4b4b4.Te6edf3targetTb4b4b4.Te6edf3valueTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3rnsHashInput Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'input'Tb4b4b4, Tb4b4b4{ Te6edf3typeTff7b72: Ta5d6ff'text'Tb4b4b4, Te6edf3placeholderTff7b72: Ta5d6ff'destination hash (32 hex)'Tb4b4b4, Te6edf3styleTff7b72: Tb4b4b4{ Te6edf3widthTff7b72: Ta5d6ff'260px'Tb4b4b4, Te6edf3fontFamilyTff7b72: Ta5d6ff'monospace' Tb4b4b4}Tb4b4b4, Te6edf3maxlengthTff7b72: Ta5d6ff'32'Tb4b4b4, Te6edf3titleTff7b72: Ta5d6ff'Remote node destination hash (32 hex chars)' Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3rnsHashInputTb4b4b4.Te6edf3value Tff7b72= Te6edf3stateTb4b4b4.Te6edf3rnsDestHashTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3rnsHashInputTb4b4b4.Te6edf3oninput Tff7b72= Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4=> Te6edf3stateTb4b4b4.Te6edf3rnsDestHashTb4b4b4.Te6edf3setTb4b4b4(Te6edf3eTb4b4b4.Te6edf3targetTb4b4b4.Te6edf3valueTb4b4b4.Te6edf3trimTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3rnsAspectInput Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'input'Tb4b4b4, Tb4b4b4{ Te6edf3typeTff7b72: Ta5d6ff'text'Tb4b4b4, Te6edf3placeholderTff7b72: Ta5d6ff'aspect'Tb4b4b4, Te6edf3styleTff7b72: Tb4b4b4{ Te6edf3widthTff7b72: Ta5d6ff'220px' Tb4b4b4}Tb4b4b4, Te6edf3titleTff7b72: Ta5d6ff'RNS destination aspect (dot-separated)' Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3rnsAspectInputTb4b4b4.Te6edf3value Tff7b72= Te6edf3stateTb4b4b4.Te6edf3rnsAspectTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3rnsAspectInputTb4b4b4.Te6edf3oninput Tff7b72= Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4=> Te6edf3stateTb4b4b4.Te6edf3rnsAspectTb4b4b4.Te6edf3setTb4b4b4(Te6edf3eTb4b4b4.Te6edf3targetTb4b4b4.Te6edf3valueTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3rnsIdentCb Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'input'Tb4b4b4, Tb4b4b4{ Te6edf3typeTff7b72: Ta5d6ff'checkbox' Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3rnsIdentCbTb4b4b4.Te6edf3checked Tff7b72= Te6edf3stateTb4b4b4.Te6edf3rnsAutoIdentifyTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3rnsIdentCbTb4b4b4.Te6edf3onchange Tff7b72= Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4=> Te6edf3stateTb4b4b4.Te6edf3rnsAutoIdentifyTb4b4b4.Te6edf3setTb4b4b4(Te6edf3eTb4b4b4.Te6edf3targetTb4b4b4.Te6edf3checkedTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3rnsIdentLabel Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'label'Tb4b4b4, Tb4b4b4{ Te6edf3styleTff7b72: Tb4b4b4{ Te6edf3displayTff7b72: Ta5d6ff'inline-flex'Tb4b4b4, Te6edf3alignItemsTff7b72: Ta5d6ff'center'Tb4b4b4, Te6edf3gapTff7b72: Ta5d6ff'4px'Tb4b4b4, Te6edf3cursorTff7b72: Ta5d6ff'pointer'Tb4b4b4, Te6edf3colorTff7b72: Ta5d6ff'var(--muted)' Tb4b4b4}Tb4b4b4, Te6edf3titleTff7b72: Ta5d6ff'Send local identity on link establishment (required by /provision ALLOW_LIST)' Tb4b4b4}Tb4b4b4, Tb4b4b4[Te6edf3rnsIdentCbTb4b4b4, Ta5d6ff'authenticate'Tb4b4b4]Tb4b4b4)Tb4b4b4;
Te6edf3rnsHostTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3rnsUrlInputTb4b4b4)Tb4b4b4;
Te6edf3rnsHostTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3rnsHashInputTb4b4b4)Tb4b4b4;
Te6edf3rnsHostTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3rnsAspectInputTb4b4b4)Tb4b4b4;
Te6edf3rnsHostTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3rnsIdentLabelTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3connectBtn Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'button'Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3disconnectBtn Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'button'Tb4b4b4, Tff7b72nullTb4b4b4, Ta5d6ff'Disconnect'Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3autoCheckbox Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'input'Tb4b4b4, Tb4b4b4{ Te6edf3typeTff7b72: Ta5d6ff'checkbox' Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3autoCheckboxTb4b4b4.Te6edf3checked Tff7b72= Te6edf3stateTb4b4b4.Te6edf3autoReconnectTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3autoCheckboxTb4b4b4.Te6edf3onchange Tff7b72= Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4=> Te6edf3stateTb4b4b4.Te6edf3autoReconnectTb4b4b4.Te6edf3setTb4b4b4(Te6edf3eTb4b4b4.Te6edf3targetTb4b4b4.Te6edf3checkedTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3autoLabel Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'label'Tb4b4b4, Tb4b4b4{ Te6edf3styleTff7b72: Tb4b4b4{ Te6edf3displayTff7b72: Ta5d6ff'inline-flex'Tb4b4b4, Te6edf3alignItemsTff7b72: Ta5d6ff'center'Tb4b4b4, Te6edf3gapTff7b72: Ta5d6ff'4px'Tb4b4b4, Te6edf3cursorTff7b72: Ta5d6ff'pointer'Tb4b4b4, Te6edf3colorTff7b72: Ta5d6ff'var(--muted)' Tb4b4b4}Tb4b4b4, Te6edf3titleTff7b72: Ta5d6ff'Reconnect automatically after a reboot to capture early boot logs' Tb4b4b4}Tb4b4b4, Tb4b4b4[Te6edf3autoCheckboxTb4b4b4, Ta5d6ff'auto-reconnect'Tb4b4b4]Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3pill Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'span'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'pill' Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3opts Tff7b72= Tb4b4b4[Tb4b4b4[Ta5d6ff'serial'Tb4b4b4,Ta5d6ff'Serial'Tb4b4b4]Tb4b4b4, Tb4b4b4[Ta5d6ff'ble'Tb4b4b4,Ta5d6ff'Bluetooth'Tb4b4b4]Tb4b4b4, Tb4b4b4[Ta5d6ff'ws'Tb4b4b4,Ta5d6ff'WebSocket'Tb4b4b4]Tb4b4b4, Tb4b4b4[Ta5d6ff'rns'Tb4b4b4,Ta5d6ff'RNS (via MeshChatX)'Tb4b4b4]Tb4b4b4]Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72const Tb4b4b4[Te6edf3vTb4b4b4, Te6edf3lblTb4b4b4] Tff7b72of Te6edf3optsTb4b4b4) Te6edf3selTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'option'Tb4b4b4, Tb4b4b4{ Te6edf3valueTff7b72: Te6edf3v Tb4b4b4}Tb4b4b4, Te6edf3lblTb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3selTb4b4b4.Te6edf3value Tff7b72= Te6edf3stateTb4b4b4.Te6edf3transportNameTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3selTb4b4b4.Te6edf3onchange Tff7b72= Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4=> Te6edf3stateTb4b4b4.Te6edf3transportNameTb4b4b4.Te6edf3setTb4b4b4(Te6edf3eTb4b4b4.Te6edf3targetTb4b4b4.Te6edf3valueTb4b4b4)Tb4b4b4;
Te6edf3connectBtnTb4b4b4.Te6edf3onclick Tff7b72= Te6edf3doConnectTb4b4b4;
Te6edf3disconnectBtnTb4b4b4.Te6edf3onclick Tff7b72= Te6edf3doDisconnectTb4b4b4;

Te6edf3rootTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'strong'Tb4b4b4, Tff7b72nullTb4b4b4, Ta5d6ff'RNode Console'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3rootTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'span'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'sep' Tb4b4b4}Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3rootTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'label'Tb4b4b4, Tff7b72nullTb4b4b4, Ta5d6ff'Transport: 'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3rootTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3selTb4b4b4)Tb4b4b4;
Te6edf3rootTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3wsHostTb4b4b4)Tb4b4b4;
Te6edf3rootTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3rnsHostTb4b4b4)Tb4b4b4;
Te6edf3rootTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3connectBtnTb4b4b4)Tb4b4b4;
Te6edf3rootTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3disconnectBtnTb4b4b4)Tb4b4b4;
Te6edf3rootTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3autoLabelTb4b4b4)Tb4b4b4;
Te6edf3rootTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'span'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'spacer' Tb4b4b4}Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3rootTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3pillTb4b4b4)Tb4b4b4;

T8b949e// Elapsed-time ticker state for the connecting badge. Declared outside
T8b949e// update() so it survives across calls (it's the same closure each time).
Tff7b72let Te6edf3connectingStartedAt Tff7b72= Tff7b72nullTb4b4b4;
Tff7b72let Te6edf3elapsedTimer Tff7b72= Tff7b72nullTb4b4b4;
Tff7b72function Te6edf3updateTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3conn Tff7b72= Te6edf3stateTb4b4b4.Te6edf3connTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3tname Tff7b72= Te6edf3stateTb4b4b4.Te6edf3transportNameTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3reconnecting Tff7b72= Te6edf3stateTb4b4b4.Te6edf3reconnectingTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3connecting Tff7b72= Te6edf3connTb4b4b4.Te6edf3state Tff7b72=== Ta5d6ff'connecting' Tff7b72&& Tff7b72!Te6edf3reconnectingTb4b4b4;
Tff7b72const Te6edf3connected Tff7b72= Te6edf3connTb4b4b4.Te6edf3state Tff7b72=== Ta5d6ff'connected'Tb4b4b4;
Te6edf3selTb4b4b4.Te6edf3disabled Tff7b72= Te6edf3connecting Tff7b72|| Te6edf3connected Tff7b72|| Te6edf3reconnectingTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3selTb4b4b4.Te6edf3value Tff7b72!== Te6edf3tnameTb4b4b4) Te6edf3selTb4b4b4.Te6edf3value Tff7b72= Te6edf3tnameTb4b4b4;
Tff7b72const Te6edf3showWs Tff7b72= Tb4b4b4(Te6edf3tname Tff7b72=== Ta5d6ff'ws'Tb4b4b4)Tb4b4b4;
Te6edf3wsInputTb4b4b4.Te6edf3styleTb4b4b4.Te6edf3display Tff7b72= Te6edf3showWs Tff7b72? Ta5d6ff'' Tff7b72: Ta5d6ff'none'Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3showWsTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tffa657documentTb4b4b4.Te6edf3activeElement Tff7b72!== Te6edf3wsInput Tff7b72&& Te6edf3wsInputTb4b4b4.Te6edf3value Tff7b72!== Te6edf3stateTb4b4b4.Te6edf3wsUrlTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4) Te6edf3wsInputTb4b4b4.Te6edf3value Tff7b72= Te6edf3stateTb4b4b4.Te6edf3wsUrlTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3wsInputTb4b4b4.Te6edf3disabled Tff7b72= Te6edf3connecting Tff7b72|| Te6edf3connected Tff7b72|| Te6edf3reconnectingTb4b4b4;
Tb4b4b4}
Tff7b72const Te6edf3showRns Tff7b72= Tb4b4b4(Te6edf3tname Tff7b72=== Ta5d6ff'rns'Tb4b4b4)Tb4b4b4;
Te6edf3rnsHostTb4b4b4.Te6edf3styleTb4b4b4.Te6edf3display Tff7b72= Te6edf3showRns Tff7b72? Ta5d6ff'' Tff7b72: Ta5d6ff'none'Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3showRnsTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tffa657documentTb4b4b4.Te6edf3activeElement Tff7b72!== Te6edf3rnsUrlInput Tff7b72&& Te6edf3rnsUrlInputTb4b4b4.Te6edf3value Tff7b72!== Te6edf3stateTb4b4b4.Te6edf3rnsUrlTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4) Te6edf3rnsUrlInputTb4b4b4.Te6edf3value Tff7b72= Te6edf3stateTb4b4b4.Te6edf3rnsUrlTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tffa657documentTb4b4b4.Te6edf3activeElement Tff7b72!== Te6edf3rnsHashInput Tff7b72&& Te6edf3rnsHashInputTb4b4b4.Te6edf3value Tff7b72!== Te6edf3stateTb4b4b4.Te6edf3rnsDestHashTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4) Te6edf3rnsHashInputTb4b4b4.Te6edf3value Tff7b72= Te6edf3stateTb4b4b4.Te6edf3rnsDestHashTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tffa657documentTb4b4b4.Te6edf3activeElement Tff7b72!== Te6edf3rnsAspectInput Tff7b72&& Te6edf3rnsAspectInputTb4b4b4.Te6edf3value Tff7b72!== Te6edf3stateTb4b4b4.Te6edf3rnsAspectTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4) Te6edf3rnsAspectInputTb4b4b4.Te6edf3value Tff7b72= Te6edf3stateTb4b4b4.Te6edf3rnsAspectTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3rnsIdentCbTb4b4b4.Te6edf3checked Tff7b72!== Te6edf3stateTb4b4b4.Te6edf3rnsAutoIdentifyTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4) Te6edf3rnsIdentCbTb4b4b4.Te6edf3checked Tff7b72= Te6edf3stateTb4b4b4.Te6edf3rnsAutoIdentifyTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3rnsUrlInputTb4b4b4.Te6edf3disabled Tff7b72= Te6edf3connecting Tff7b72|| Te6edf3connected Tff7b72|| Te6edf3reconnectingTb4b4b4;
Te6edf3rnsHashInputTb4b4b4.Te6edf3disabled Tff7b72= Te6edf3connecting Tff7b72|| Te6edf3connected Tff7b72|| Te6edf3reconnectingTb4b4b4;
Te6edf3rnsAspectInputTb4b4b4.Te6edf3disabled Tff7b72= Te6edf3connecting Tff7b72|| Te6edf3connected Tff7b72|| Te6edf3reconnectingTb4b4b4;
Te6edf3rnsIdentCbTb4b4b4.Te6edf3disabled Tff7b72= Te6edf3connecting Tff7b72|| Te6edf3connected Tff7b72|| Te6edf3reconnectingTb4b4b4;
Tb4b4b4}
Te6edf3connectBtnTb4b4b4.Te6edf3disabled Tff7b72= Te6edf3connecting Tff7b72|| Te6edf3connected Tff7b72|| Te6edf3reconnectingTb4b4b4;
Te6edf3connectBtnTb4b4b4.Te6edf3textContent Tff7b72= Te6edf3connecting Tff7b72? Ta5d6ff'Connecting…' Tff7b72: Ta5d6ff'Connect'Tb4b4b4;
T8b949e// Disconnect is also the cancel-reconnect button while reconnecting.
Te6edf3disconnectBtnTb4b4b4.Te6edf3disabled Tff7b72= Tff7b72!Te6edf3connected Tff7b72&& Tff7b72!Te6edf3reconnectingTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3autoCheckboxTb4b4b4.Te6edf3checked Tff7b72!== Te6edf3stateTb4b4b4.Te6edf3autoReconnectTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4) Te6edf3autoCheckboxTb4b4b4.Te6edf3checked Tff7b72= Te6edf3stateTb4b4b4.Te6edf3autoReconnectTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72let Te6edf3txt Tff7b72= Ta5d6ff'Disconnected'Tb4b4b4, Te6edf3cls Tff7b72= Ta5d6ff'st-idle'Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3reconnectingTb4b4b4) Tb4b4b4{ Te6edf3txt Tff7b72= Ta5d6ff'Reconnecting…'Tb4b4b4; Te6edf3cls Tff7b72= Ta5d6ff'st-connecting'Tb4b4b4; Tb4b4b4}
Tff7b72else Tff7b72if Tb4b4b4(Te6edf3connectingTb4b4b4) Tb4b4b4{
T8b949e// Show the transport-supplied phase label (e.g. "WS connecting",
T8b949e// "WS verifying", "Link connecting", "Finding path"…) plus the elapsed
T8b949e// time so the user has feedback during slow LoRa-paced steps.
Tff7b72const Te6edf3label Tff7b72= Tb4b4b4(Te6edf3connTb4b4b4.Te6edf3info Tff7b72&& Tffa657StringTb4b4b4(Te6edf3connTb4b4b4.Te6edf3infoTb4b4b4)Tb4b4b4.Te6edf3trimTb4b4b4(Tb4b4b4)Tb4b4b4) Tff7b72? Te6edf3connTb4b4b4.Te6edf3info Tff7b72: Ta5d6ff'Connecting'Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3connectingStartedAt Tff7b72=== Tff7b72nullTb4b4b4) Te6edf3connectingStartedAt Tff7b72= Tffa657DateTb4b4b4.Te6edf3nowTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3elapsedTimer Tff7b72=== Tff7b72nullTb4b4b4) Te6edf3elapsedTimer Tff7b72= Te6edf3setIntervalTb4b4b4(Te6edf3updateTb4b4b4, T79c0ff1000Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3elapsed Tff7b72= Tffa657MathTb4b4b4.Te6edf3floorTb4b4b4(Tb4b4b4(Tffa657DateTb4b4b4.Te6edf3nowTb4b4b4(Tb4b4b4) Tff7b72- Te6edf3connectingStartedAtTb4b4b4) Tff7b72/ T79c0ff1000Tb4b4b4)Tb4b4b4;
Te6edf3txt Tff7b72= Te6edf3label Tff7b72+ Ta5d6ff'… ' Tff7b72+ Te6edf3elapsed Tff7b72+ Ta5d6ff's'Tb4b4b4;
Te6edf3cls Tff7b72= Ta5d6ff'st-connecting'Tb4b4b4;
Tb4b4b4}
Tff7b72else Tff7b72if Tb4b4b4(Te6edf3connectedTb4b4b4) Tb4b4b4{ Te6edf3txt Tff7b72= Ta5d6ff'Connected' Tff7b72+ Tb4b4b4(Te6edf3connTb4b4b4.Te6edf3info Tff7b72? Ta5d6ff`Ta5d6ff (Tffd700${Te6edf3connTb4b4b4.Te6edf3infoTffd700}Ta5d6ff)Ta5d6ff` Tff7b72: Ta5d6ff''Tb4b4b4)Tb4b4b4; Te6edf3cls Tff7b72= Ta5d6ff'st-ok'Tb4b4b4; Tb4b4b4}
Tff7b72else Tff7b72if Tb4b4b4(Te6edf3connTb4b4b4.Te6edf3state Tff7b72=== Ta5d6ff'error'Tb4b4b4) Tb4b4b4{ Te6edf3txt Tff7b72= Ta5d6ff'Error: ' Tff7b72+ Tb4b4b4(Te6edf3connTb4b4b4.Te6edf3info Tff7b72|| Ta5d6ff''Tb4b4b4)Tb4b4b4; Te6edf3cls Tff7b72= Ta5d6ff'st-err'Tb4b4b4; Tb4b4b4}
T8b949e// Stop the elapsed-time ticker once we leave 'connecting'.
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3connecting Tff7b72&& Tff7b72!Te6edf3reconnectingTb4b4b4) Tb4b4b4{
Te6edf3connectingStartedAt Tff7b72= Tff7b72nullTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3elapsedTimer Tff7b72!== Tff7b72nullTb4b4b4) Tb4b4b4{ Te6edf3clearIntervalTb4b4b4(Te6edf3elapsedTimerTb4b4b4)Tb4b4b4; Te6edf3elapsedTimer Tff7b72= Tff7b72nullTb4b4b4; Tb4b4b4}
Tb4b4b4}
Te6edf3pillTb4b4b4.Te6edf3className Tff7b72= Ta5d6ff'pill ' Tff7b72+ Te6edf3clsTb4b4b4;
Te6edf3pillTb4b4b4.Te6edf3textContent Tff7b72= Te6edf3txtTb4b4b4;
Tb4b4b4}
Te6edf3updateTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3connTb4b4b4.Te6edf3subscribeTb4b4b4(Te6edf3updateTb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3transportNameTb4b4b4.Te6edf3subscribeTb4b4b4(Te6edf3updateTb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3wsUrlTb4b4b4.Te6edf3subscribeTb4b4b4(Te6edf3updateTb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3rnsUrlTb4b4b4.Te6edf3subscribeTb4b4b4(Te6edf3updateTb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3rnsDestHashTb4b4b4.Te6edf3subscribeTb4b4b4(Te6edf3updateTb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3rnsAspectTb4b4b4.Te6edf3subscribeTb4b4b4(Te6edf3updateTb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3rnsAutoIdentifyTb4b4b4.Te6edf3subscribeTb4b4b4(Te6edf3updateTb4b4b4)Tb4b4b4;

Te6edf3stateTb4b4b4.Te6edf3autoReconnectTb4b4b4.Te6edf3subscribeTb4b4b4(Te6edf3updateTb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3reconnectingTb4b4b4.Te6edf3subscribeTb4b4b4(Te6edf3updateTb4b4b4)Tb4b4b4;
Tff7b72return Te6edf3rootTb4b4b4;
Tb4b4b4}
Te6edf3slotsTb4b4b4.Te6edf3topbarTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3buildTopBarTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;

T8b949e// ----- Tab bar (in place) -----
Tff7b72function Te6edf3buildTabBarTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3root Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'tabbar' Tb4b4b4}Tb4b4b4)Tb4b4b4;
T8b949e// Info merged into Node Status; that's now the always-available landing tab.
Tff7b72const Te6edf3tabs Tff7b72= Tb4b4b4[
Tb4b4b4{ Te6edf3idTff7b72: Ta5d6ff'status'Tb4b4b4, Te6edf3labelTff7b72: Ta5d6ff'Node Status' Tb4b4b4}Tb4b4b4,
Tb4b4b4{ Te6edf3idTff7b72: Ta5d6ff'nodeconfig'Tb4b4b4, Te6edf3labelTff7b72: Ta5d6ff'Node Config' Tb4b4b4}Tb4b4b4,
Tb4b4b4{ Te6edf3idTff7b72: Ta5d6ff'config'Tb4b4b4, Te6edf3labelTff7b72: Ta5d6ff'Transport Config' Tb4b4b4}Tb4b4b4,
Tb4b4b4{ Te6edf3idTff7b72: Ta5d6ff'logs'Tb4b4b4, Te6edf3labelTff7b72: Ta5d6ff'Logs' Tb4b4b4}Tb4b4b4,
Tb4b4b4]Tb4b4b4;
Tff7b72const Te6edf3buttons Tff7b72= Tb4b4b4{Tb4b4b4}Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3t Tff7b72of Te6edf3tabsTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3b Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'button'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'tab'Tb4b4b4, Te6edf3onclickTff7b72: Tb4b4b4(Tb4b4b4) Tb4b4b4=> Te6edf3stateTb4b4b4.Te6edf3activeTabTb4b4b4.Te6edf3setTb4b4b4(Te6edf3tTb4b4b4.Te6edf3idTb4b4b4) Tb4b4b4}Tb4b4b4, Te6edf3tTb4b4b4.Te6edf3labelTb4b4b4)Tb4b4b4;
Te6edf3buttonsTb4b4b4[Te6edf3tTb4b4b4.Te6edf3idTb4b4b4] Tff7b72= Te6edf3bTb4b4b4;
Te6edf3rootTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3bTb4b4b4)Tb4b4b4;
Tb4b4b4}
T8b949e// Transport Config is only meaningful when microReticulum is part of the
T8b949e// build — detected by the presence of any namespace with id < 100 (RNS
T8b949e// reserves 1-99 for built-in namespaces per RNode_Firmware.ino comments;
T8b949e// 100+ is for app namespaces like 'general' which exists even with HAS_RNS
T8b949e// undefined). Legacy firmware that doesn't speak Provisioning at all leaves
T8b949e// state.schema = null, in which case we also hide the tab.
Tff7b72function Te6edf3transportConfigVisibleTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3schema Tff7b72= Te6edf3stateTb4b4b4.Te6edf3schemaTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3schema Tff7b72|| Tff7b72!Tffa657ArrayTb4b4b4.Te6edf3isArrayTb4b4b4(Te6edf3schemaTb4b4b4.Te6edf3namespacesTb4b4b4)Tb4b4b4) Tff7b72return Tff7b72falseTb4b4b4;
Tff7b72return Te6edf3schemaTb4b4b4.Te6edf3namespacesTb4b4b4.Te6edf3someTb4b4b4(Te6edf3n Tb4b4b4=> Tffa657NumberTb4b4b4(Te6edf3nTb4b4b4.Te6edf3idTb4b4b4) Tff7b72< T79c0ff100Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72function Te6edf3updateTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3active Tff7b72= Te6edf3stateTb4b4b4.Te6edf3activeTabTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
T8b949e// Treat "reconnecting" as not-yet-connected so per-tab actions don't fire
T8b949e// against a transport that's still being re-established.
Tff7b72const Te6edf3connected Tff7b72= Te6edf3stateTb4b4b4.Te6edf3connTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3state Tff7b72=== Ta5d6ff'connected' Tff7b72&& Tff7b72!Te6edf3stateTb4b4b4.Te6edf3reconnectingTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
T8b949e// Capability-gated visibility: every tab other than Node Status only
T8b949e// surfaces once we've positively confirmed the active transport supports
T8b949e// it. While disconnected (or reconnecting), only Node Status shows.
T8b949e// - Node Config (legacy KISS opcodes): requires legacySupported === true
T8b949e// (CMD_BOARD probe succeeded). Starts null and the probe takes up to
T8b949e// 1500ms, during which we keep the tab hidden — a brief delay is
T8b949e// preferable to a flash-then-hide.
T8b949e// - Transport Config (Provisioning + RNS namespaces): requires
T8b949e// transportConfigVisible() (schema fetched and has an id<100 ns).
T8b949e// - Logs (KISS CMD_LOG frames from the device): not delivered over RNS
T8b949e// because RnsTransport only forwards CMD_PROVISION_RSP frames back.
Tff7b72const Te6edf3isRns Tff7b72= Te6edf3stateTb4b4b4.Te6edf3transportNameTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4) Tff7b72=== Ta5d6ff'rns'Tb4b4b4;
Tff7b72const Te6edf3showNcfg Tff7b72= Te6edf3connected Tff7b72&& Te6edf3stateTb4b4b4.Te6edf3legacySupportedTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4) Tff7b72=== Tff7b72trueTb4b4b4;
Tff7b72const Te6edf3showCfg Tff7b72= Te6edf3connected Tff7b72&& Te6edf3transportConfigVisibleTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3showLogs Tff7b72= Te6edf3connected Tff7b72&& Tff7b72!Te6edf3isRnsTb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3t Tff7b72of Te6edf3tabsTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3b Tff7b72= Te6edf3buttonsTb4b4b4[Te6edf3tTb4b4b4.Te6edf3idTb4b4b4]Tb4b4b4;
Te6edf3bTb4b4b4.Te6edf3classListTb4b4b4.Te6edf3toggleTb4b4b4(Ta5d6ff'active'Tb4b4b4, Te6edf3active Tff7b72=== Te6edf3tTb4b4b4.Te6edf3idTb4b4b4)Tb4b4b4;
Te6edf3bTb4b4b4.Te6edf3disabled Tff7b72= Tff7b72!Te6edf3connected Tff7b72&& Te6edf3tTb4b4b4.Te6edf3id Tff7b72!== Ta5d6ff'status'Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3tTb4b4b4.Te6edf3id Tff7b72=== Ta5d6ff'config'Tb4b4b4) Te6edf3bTb4b4b4.Te6edf3styleTb4b4b4.Te6edf3display Tff7b72= Te6edf3showCfg Tff7b72? Ta5d6ff'' Tff7b72: Ta5d6ff'none'Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3tTb4b4b4.Te6edf3id Tff7b72=== Ta5d6ff'nodeconfig'Tb4b4b4) Te6edf3bTb4b4b4.Te6edf3styleTb4b4b4.Te6edf3display Tff7b72= Te6edf3showNcfg Tff7b72? Ta5d6ff'' Tff7b72: Ta5d6ff'none'Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3tTb4b4b4.Te6edf3id Tff7b72=== Ta5d6ff'logs'Tb4b4b4) Te6edf3bTb4b4b4.Te6edf3styleTb4b4b4.Te6edf3display Tff7b72= Te6edf3showLogs Tff7b72? Ta5d6ff'' Tff7b72: Ta5d6ff'none'Tb4b4b4;
Tb4b4b4}
T8b949e// Redirect away from any hidden tab so the user isn't on an invisible body.
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3showCfg Tff7b72&& Te6edf3active Tff7b72=== Ta5d6ff'config'Tb4b4b4) Te6edf3stateTb4b4b4.Te6edf3activeTabTb4b4b4.Te6edf3setTb4b4b4(Ta5d6ff'status'Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3showNcfg Tff7b72&& Te6edf3active Tff7b72=== Ta5d6ff'nodeconfig'Tb4b4b4) Te6edf3stateTb4b4b4.Te6edf3activeTabTb4b4b4.Te6edf3setTb4b4b4(Ta5d6ff'status'Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3showLogs Tff7b72&& Te6edf3active Tff7b72=== Ta5d6ff'logs'Tb4b4b4) Te6edf3stateTb4b4b4.Te6edf3activeTabTb4b4b4.Te6edf3setTb4b4b4(Ta5d6ff'status'Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3updateTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3activeTabTb4b4b4.Te6edf3subscribeTb4b4b4(Te6edf3updateTb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3connTb4b4b4.Te6edf3subscribeTb4b4b4(Te6edf3updateTb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3reconnectingTb4b4b4.Te6edf3subscribeTb4b4b4(Te6edf3updateTb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3schemaTb4b4b4.Te6edf3subscribeTb4b4b4(Te6edf3updateTb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3legacySupportedTb4b4b4.Te6edf3subscribeTb4b4b4(Te6edf3updateTb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3transportNameTb4b4b4.Te6edf3subscribeTb4b4b4(Te6edf3updateTb4b4b4)Tb4b4b4;
Tff7b72return Te6edf3rootTb4b4b4;
Tb4b4b4}
Te6edf3slotsTb4b4b4.Te6edf3tabbarTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3buildTabBarTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;

T8b949e// ----- Tab bodies -----

Tff7b72function Te6edf3buildStatusTabTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3root Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'tab-body' Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72function Te6edf3rowTb4b4b4(Te6edf3labelTb4b4b4, Te6edf3valTb4b4b4, Te6edf3unitTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3val Tff7b72== Tff7b72nullTb4b4b4) Tff7b72return Tff7b72nullTb4b4b4;
Tff7b72return Te6edf3elTb4b4b4(Ta5d6ff'tr'Tb4b4b4, Tff7b72nullTb4b4b4, Tb4b4b4[Te6edf3elTb4b4b4(Ta5d6ff'td'Tb4b4b4, Tff7b72nullTb4b4b4, Te6edf3labelTb4b4b4)Tb4b4b4, Te6edf3elTb4b4b4(Ta5d6ff'td'Tb4b4b4, Tff7b72nullTb4b4b4, Te6edf3val Tff7b72+ Tb4b4b4(Te6edf3unit Tff7b72? Ta5d6ff' ' Tff7b72+ Te6edf3unit Tff7b72: Ta5d6ff''Tb4b4b4)Tb4b4b4)Tb4b4b4]Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72function Te6edf3sectionTb4b4b4(Te6edf3titleTb4b4b4, Te6edf3rowsTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3r Tff7b72= Te6edf3rowsTb4b4b4.Te6edf3filterTb4b4b4(Te6edf3x Tb4b4b4=> Te6edf3x Tff7b72!= Tff7b72nullTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3rTb4b4b4.Te6edf3length Tff7b72=== T79c0ff0Tb4b4b4) Tff7b72return Tff7b72nullTb4b4b4;
Tff7b72return Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'status-sec' Tb4b4b4}Tb4b4b4, Tb4b4b4[Te6edf3elTb4b4b4(Ta5d6ff'h3'Tb4b4b4, Tff7b72nullTb4b4b4, Te6edf3titleTb4b4b4)Tb4b4b4, Te6edf3elTb4b4b4(Ta5d6ff'table'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'kv' Tb4b4b4}Tb4b4b4, Te6edf3rTb4b4b4)Tb4b4b4]Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72function Te6edf3updateTb4b4b4(Tb4b4b4)Tb4b4b4{
Te6edf3rootTb4b4b4.Te6edf3innerHTML Tff7b72= Ta5d6ff''Tb4b4b4;
Tff7b72const Te6edf3conn Tff7b72= Te6edf3stateTb4b4b4.Te6edf3connTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3connected Tff7b72= Te6edf3connTb4b4b4.Te6edf3state Tff7b72=== Ta5d6ff'connected'Tb4b4b4;
Tff7b72const Te6edf3info Tff7b72= Te6edf3stateTb4b4b4.Te6edf3infoTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
T8b949e// (Reboot banner is rendered globally outside the tab body so it stays
T8b949e// visible on every tab. See buildRebootBanner() near the slot setup.)
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3connectedTb4b4b4) Tb4b4b4{
Te6edf3rootTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'em'Tb4b4b4, Tff7b72nullTb4b4b4, Ta5d6ff'Select a transport and click Connect.'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72returnTb4b4b4;
Tb4b4b4}

T8b949e// ---- Device section (merged from former Info tab) ----
Tff7b72const Te6edf3ncDev Tff7b72= Te6edf3stateTb4b4b4.Te6edf3nodeCfgDeviceInfoTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3devRows Tff7b72= Tb4b4b4[
Te6edf3info Tff7b72? Te6edf3rowTb4b4b4(Ta5d6ff'Firmware'Tb4b4b4, Tffa657StringTb4b4b4(Te6edf3infoTb4b4b4.Te6edf3firmwareVersion Tff7b72?? Ta5d6ff''Tb4b4b4)Tb4b4b4) Tff7b72: Tff7b72nullTb4b4b4,
Te6edf3info Tff7b72? Te6edf3rowTb4b4b4(Ta5d6ff'Schema version'Tb4b4b4, Tffa657StringTb4b4b4(Te6edf3infoTb4b4b4.Te6edf3schemaVersion Tff7b72?? Ta5d6ff''Tb4b4b4)Tb4b4b4) Tff7b72: Tff7b72nullTb4b4b4,
Te6edf3ncDev Tff7b72&& Te6edf3ncDevTb4b4b4.Te6edf3board Tff7b72!= Tff7b72null Tff7b72? Te6edf3rowTb4b4b4(Ta5d6ff'Board'Tb4b4b4, Ta5d6ff`Tffd700${Te6edf3BOARD_NAMESTb4b4b4[Te6edf3ncDevTb4b4b4.Te6edf3boardTb4b4b4] Tff7b72|| Ta5d6ff'Unknown'Tffd700}Ta5d6ff (0xTffd700${Te6edf3ncDevTb4b4b4.Te6edf3boardTb4b4b4.Te6edf3toStringTb4b4b4(T79c0ff16Tb4b4b4)Tb4b4b4.Te6edf3padStartTb4b4b4(T79c0ff2Tb4b4b4,Ta5d6ff'0'Tb4b4b4)Tffd700}Ta5d6ff)Ta5d6ff`Tb4b4b4) Tff7b72: Tff7b72nullTb4b4b4,
Te6edf3ncDev Tff7b72&& Te6edf3ncDevTb4b4b4.Te6edf3platform Tff7b72!= Tff7b72null Tff7b72? Te6edf3rowTb4b4b4(Ta5d6ff'Platform'Tb4b4b4, Ta5d6ff`Tffd700${Te6edf3PLATFORM_NAMESTb4b4b4[Te6edf3ncDevTb4b4b4.Te6edf3platformTb4b4b4] Tff7b72|| Ta5d6ff'Unknown'Tffd700}Ta5d6ff (0xTffd700${Te6edf3ncDevTb4b4b4.Te6edf3platformTb4b4b4.Te6edf3toStringTb4b4b4(T79c0ff16Tb4b4b4)Tb4b4b4.Te6edf3padStartTb4b4b4(T79c0ff2Tb4b4b4,Ta5d6ff'0'Tb4b4b4)Tffd700}Ta5d6ff)Ta5d6ff`Tb4b4b4) Tff7b72: Tff7b72nullTb4b4b4,
Te6edf3ncDev Tff7b72&& Te6edf3ncDevTb4b4b4.Te6edf3mcu Tff7b72!= Tff7b72null Tff7b72? Te6edf3rowTb4b4b4(Ta5d6ff'MCU'Tb4b4b4, Ta5d6ff`Tffd700${Te6edf3MCU_NAMESTb4b4b4[Te6edf3ncDevTb4b4b4.Te6edf3mcuTb4b4b4] Tff7b72|| Ta5d6ff'Unknown'Tffd700}Ta5d6ff (0xTffd700${Te6edf3ncDevTb4b4b4.Te6edf3mcuTb4b4b4.Te6edf3toStringTb4b4b4(T79c0ff16Tb4b4b4)Tb4b4b4.Te6edf3padStartTb4b4b4(T79c0ff2Tb4b4b4,Ta5d6ff'0'Tb4b4b4)Tffd700}Ta5d6ff)Ta5d6ff`Tb4b4b4) Tff7b72: Tff7b72nullTb4b4b4,
Te6edf3info Tff7b72? Te6edf3rowTb4b4b4(Ta5d6ff'Needs reboot'Tb4b4b4, Te6edf3infoTb4b4b4.Te6edf3needsReboot Tff7b72? Ta5d6ff'yes' Tff7b72: Ta5d6ff'no'Tb4b4b4) Tff7b72: Tff7b72nullTb4b4b4,
Tb4b4b4]Tb4b4b4;
Tff7b72const Te6edf3devSection Tff7b72= Te6edf3sectionTb4b4b4(Ta5d6ff'Device'Tb4b4b4, Te6edf3devRowsTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3devSectionTb4b4b4) Te6edf3rootTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3devSectionTb4b4b4)Tb4b4b4;

T8b949e// ---- Live status sections (driven by CMD_STAT_*) ----
Tff7b72const Te6edf3s Tff7b72= Te6edf3stateTb4b4b4.Te6edf3nodeStatusTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3batStates Tff7b72= Tb4b4b4[Ta5d6ff'unknown'Tb4b4b4,Ta5d6ff'discharging'Tb4b4b4,Ta5d6ff'charging'Tb4b4b4,Ta5d6ff'charged'Tb4b4b4]Tb4b4b4;
Tff7b72const Te6edf3liveSections Tff7b72= Tb4b4b4[
Te6edf3sectionTb4b4b4(Ta5d6ff'Radio link'Tb4b4b4, Tb4b4b4[
Te6edf3rowTb4b4b4(Ta5d6ff'Last RSSI'Tb4b4b4, Te6edf3sTb4b4b4.Te6edf3lastRssiTb4b4b4, Ta5d6ff'dBm'Tb4b4b4)Tb4b4b4,
Te6edf3rowTb4b4b4(Ta5d6ff'Last SNR'Tb4b4b4, Te6edf3sTb4b4b4.Te6edf3lastSnr Tff7b72!= Tff7b72null Tff7b72? Te6edf3sTb4b4b4.Te6edf3lastSnrTb4b4b4.Te6edf3toFixedTb4b4b4(T79c0ff2Tb4b4b4) Tff7b72: Tff7b72nullTb4b4b4, Ta5d6ff'dB'Tb4b4b4)Tb4b4b4,
Te6edf3rowTb4b4b4(Ta5d6ff'Current RSSI'Tb4b4b4, Te6edf3sTb4b4b4.Te6edf3currentRssiTb4b4b4, Ta5d6ff'dBm'Tb4b4b4)Tb4b4b4,
Te6edf3rowTb4b4b4(Ta5d6ff'Noise floor'Tb4b4b4, Te6edf3sTb4b4b4.Te6edf3noiseFloorTb4b4b4, Ta5d6ff'dBm'Tb4b4b4)Tb4b4b4,
Te6edf3rowTb4b4b4(Ta5d6ff'Interference'Tb4b4b4, Te6edf3sTb4b4b4.Te6edf3interferenceRssi Tff7b72!= Tff7b72null Tff7b72? Te6edf3sTb4b4b4.Te6edf3interferenceRssi Tff7b72+ Ta5d6ff' dBm' Tff7b72: Tff7b72nullTb4b4b4)Tb4b4b4,
Tb4b4b4]Tb4b4b4)Tb4b4b4,
Te6edf3sectionTb4b4b4(Ta5d6ff'Channel'Tb4b4b4, Tb4b4b4[
Te6edf3rowTb4b4b4(Ta5d6ff'Airtime (short)'Tb4b4b4, Te6edf3sTb4b4b4.Te6edf3airtimeShort Tff7b72!= Tff7b72null Tff7b72? Tb4b4b4(Te6edf3sTb4b4b4.Te6edf3airtimeShort Tff7b72* T79c0ff100Tb4b4b4)Tb4b4b4.Te6edf3toFixedTb4b4b4(T79c0ff2Tb4b4b4) Tff7b72: Tff7b72nullTb4b4b4, Ta5d6ff'%'Tb4b4b4)Tb4b4b4,
Te6edf3rowTb4b4b4(Ta5d6ff'Airtime (long)'Tb4b4b4, Te6edf3sTb4b4b4.Te6edf3airtimeLong Tff7b72!= Tff7b72null Tff7b72? Tb4b4b4(Te6edf3sTb4b4b4.Te6edf3airtimeLong Tff7b72* T79c0ff100Tb4b4b4)Tb4b4b4.Te6edf3toFixedTb4b4b4(T79c0ff2Tb4b4b4) Tff7b72: Tff7b72nullTb4b4b4, Ta5d6ff'%'Tb4b4b4)Tb4b4b4,
Te6edf3rowTb4b4b4(Ta5d6ff'Utilization (short)'Tb4b4b4, Te6edf3sTb4b4b4.Te6edf3channelUtilShort Tff7b72!= Tff7b72null Tff7b72? Tb4b4b4(Te6edf3sTb4b4b4.Te6edf3channelUtilShort Tff7b72* T79c0ff100Tb4b4b4)Tb4b4b4.Te6edf3toFixedTb4b4b4(T79c0ff2Tb4b4b4) Tff7b72: Tff7b72nullTb4b4b4, Ta5d6ff'%'Tb4b4b4)Tb4b4b4,
Te6edf3rowTb4b4b4(Ta5d6ff'Utilization (long)'Tb4b4b4, Te6edf3sTb4b4b4.Te6edf3channelUtilLong Tff7b72!= Tff7b72null Tff7b72? Tb4b4b4(Te6edf3sTb4b4b4.Te6edf3channelUtilLong Tff7b72* T79c0ff100Tb4b4b4)Tb4b4b4.Te6edf3toFixedTb4b4b4(T79c0ff2Tb4b4b4) Tff7b72: Tff7b72nullTb4b4b4, Ta5d6ff'%'Tb4b4b4)Tb4b4b4,
Tb4b4b4]Tb4b4b4)Tb4b4b4,
Te6edf3sectionTb4b4b4(Ta5d6ff'Counters'Tb4b4b4, Tb4b4b4[Te6edf3rowTb4b4b4(Ta5d6ff'RX packets'Tb4b4b4, Te6edf3sTb4b4b4.Te6edf3rxPacketsTb4b4b4)Tb4b4b4, Te6edf3rowTb4b4b4(Ta5d6ff'TX packets'Tb4b4b4, Te6edf3sTb4b4b4.Te6edf3txPacketsTb4b4b4)Tb4b4b4]Tb4b4b4)Tb4b4b4,
Te6edf3sectionTb4b4b4(Ta5d6ff'PHY parameters'Tb4b4b4, Tb4b4b4[
Te6edf3rowTb4b4b4(Ta5d6ff'Symbol time'Tb4b4b4, Te6edf3sTb4b4b4.Te6edf3symbolTimeUsTb4b4b4, Ta5d6ff'µs'Tb4b4b4)Tb4b4b4,
Te6edf3rowTb4b4b4(Ta5d6ff'Symbol rate'Tb4b4b4, Te6edf3sTb4b4b4.Te6edf3symbolRateTb4b4b4, Ta5d6ff'sym/s'Tb4b4b4)Tb4b4b4,
Te6edf3rowTb4b4b4(Ta5d6ff'Preamble symbols'Tb4b4b4, Te6edf3sTb4b4b4.Te6edf3preambleSymbolsTb4b4b4)Tb4b4b4,
Te6edf3rowTb4b4b4(Ta5d6ff'Preamble time'Tb4b4b4, Te6edf3sTb4b4b4.Te6edf3preambleTimeMsTb4b4b4, Ta5d6ff'ms'Tb4b4b4)Tb4b4b4,
Te6edf3rowTb4b4b4(Ta5d6ff'CSMA slot'Tb4b4b4, Te6edf3sTb4b4b4.Te6edf3csmaSlotMsTb4b4b4, Ta5d6ff'ms'Tb4b4b4)Tb4b4b4,
Te6edf3rowTb4b4b4(Ta5d6ff'DIFS'Tb4b4b4, Te6edf3sTb4b4b4.Te6edf3difsMsTb4b4b4, Ta5d6ff'ms'Tb4b4b4)Tb4b4b4,
Tb4b4b4]Tb4b4b4)Tb4b4b4,
Te6edf3sectionTb4b4b4(Ta5d6ff'CSMA'Tb4b4b4, Tb4b4b4[Te6edf3rowTb4b4b4(Ta5d6ff'CW band'Tb4b4b4, Te6edf3sTb4b4b4.Te6edf3cwBandTb4b4b4)Tb4b4b4, Te6edf3rowTb4b4b4(Ta5d6ff'CW min'Tb4b4b4, Te6edf3sTb4b4b4.Te6edf3cwMinTb4b4b4)Tb4b4b4, Te6edf3rowTb4b4b4(Ta5d6ff'CW max'Tb4b4b4, Te6edf3sTb4b4b4.Te6edf3cwMaxTb4b4b4)Tb4b4b4]Tb4b4b4)Tb4b4b4,
Te6edf3sectionTb4b4b4(Ta5d6ff'Power'Tb4b4b4, Tb4b4b4[
Te6edf3rowTb4b4b4(Ta5d6ff'Battery'Tb4b4b4, Te6edf3sTb4b4b4.Te6edf3batteryPercent Tff7b72!= Tff7b72null Tff7b72? Ta5d6ff`Tffd700${Te6edf3sTb4b4b4.Te6edf3batteryPercentTffd700}Ta5d6ff% (Tffd700${Te6edf3batStatesTb4b4b4[Te6edf3sTb4b4b4.Te6edf3batteryState Tff7b72|| T79c0ff0Tb4b4b4]Tffd700}Ta5d6ff)Ta5d6ff` Tff7b72: Tff7b72nullTb4b4b4)Tb4b4b4,
Te6edf3rowTb4b4b4(Ta5d6ff'Temperature'Tb4b4b4, Te6edf3sTb4b4b4.Te6edf3temperatureCTb4b4b4, Ta5d6ff'°C'Tb4b4b4)Tb4b4b4,
Tb4b4b4]Tb4b4b4)Tb4b4b4,
Tb4b4b4]Tb4b4b4.Te6edf3filterTb4b4b4(Te6edf3x Tb4b4b4=> Te6edf3x Tff7b72!= Tff7b72nullTb4b4b4)Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3sec Tff7b72of Te6edf3liveSectionsTb4b4b4) Te6edf3rootTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3secTb4b4b4)Tb4b4b4;

Tff7b72if Tb4b4b4(Tff7b72!Te6edf3devSection Tff7b72&& Te6edf3liveSectionsTb4b4b4.Te6edf3length Tff7b72=== T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3rootTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'em'Tb4b4b4, Tff7b72nullTb4b4b4, Ta5d6ff'Waiting for status frames…'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}

T8b949e// ---- Danger zone (always at the bottom when connected) ----
Te6edf3rootTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'h3'Tb4b4b4, Tff7b72nullTb4b4b4, Ta5d6ff'Danger zone'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3rootTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Te6edf3styleTff7b72: Tb4b4b4{ Te6edf3displayTff7b72: Ta5d6ff'flex'Tb4b4b4, Te6edf3gapTff7b72: Ta5d6ff'8px' Tb4b4b4} Tb4b4b4}Tb4b4b4, Tb4b4b4[
Te6edf3elTb4b4b4(Ta5d6ff'button'Tb4b4b4, Tb4b4b4{ Te6edf3onclickTff7b72: Te6edf3rebootTb4b4b4, Te6edf3disabledTff7b72: Tff7b72!Te6edf3connected Tb4b4b4}Tb4b4b4, Ta5d6ff'Reboot'Tb4b4b4)Tb4b4b4,
Te6edf3elTb4b4b4(Ta5d6ff'button'Tb4b4b4, Tb4b4b4{ Te6edf3onclickTff7b72: Te6edf3factoryResetTb4b4b4, Te6edf3disabledTff7b72: Tff7b72!Te6edf3connected Tb4b4b4}Tb4b4b4, Ta5d6ff'Factory reset'Tb4b4b4)Tb4b4b4,
Tb4b4b4]Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3updateTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3bodyCleanupsTb4b4b4.Te6edf3pushTb4b4b4(Te6edf3stateTb4b4b4.Te6edf3nodeStatusTb4b4b4.Te6edf3subscribeTb4b4b4(Te6edf3updateTb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3bodyCleanupsTb4b4b4.Te6edf3pushTb4b4b4(Te6edf3stateTb4b4b4.Te6edf3infoTb4b4b4.Te6edf3subscribeTb4b4b4(Te6edf3updateTb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3bodyCleanupsTb4b4b4.Te6edf3pushTb4b4b4(Te6edf3stateTb4b4b4.Te6edf3connTb4b4b4.Te6edf3subscribeTb4b4b4(Te6edf3updateTb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3bodyCleanupsTb4b4b4.Te6edf3pushTb4b4b4(Te6edf3stateTb4b4b4.Te6edf3nodeCfgDeviceInfoTb4b4b4.Te6edf3subscribeTb4b4b4(Te6edf3updateTb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3bodyCleanupsTb4b4b4.Te6edf3pushTb4b4b4(Te6edf3stateTb4b4b4.Te6edf3nodeCfgNeedsRebootTb4b4b4.Te6edf3subscribeTb4b4b4(Te6edf3updateTb4b4b4)Tb4b4b4)Tb4b4b4;
T8b949e// Auto-fetch device info on first activation when connected so board/platform/MCU
T8b949e// appear without the user having to visit a separate sub-tab.
Tff7b72if Tb4b4b4(Te6edf3stateTb4b4b4.Te6edf3connTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3state Tff7b72=== Ta5d6ff'connected' Tff7b72&& Tff7b72!Te6edf3stateTb4b4b4.Te6edf3nodeCfgDeviceInfoTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4) Tff7b72&& Te6edf3legacyTb4b4b4) Tb4b4b4{
Te6edf3legacyTb4b4b4.Te6edf3readDeviceInfoTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3thenTb4b4b4(Te6edf3d Tb4b4b4=> Te6edf3stateTb4b4b4.Te6edf3nodeCfgDeviceInfoTb4b4b4.Te6edf3setTb4b4b4(Te6edf3dTb4b4b4)Tb4b4b4)Tb4b4b4.Tff7b72catchTb4b4b4(Te6edf3e Tb4b4b4=> Te6edf3consoleTb4b4b4.Te6edf3errorTb4b4b4(Ta5d6ff'Node Status device info fetch:'Tb4b4b4, Te6edf3eTb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72return Te6edf3rootTb4b4b4;
Tb4b4b4}

Tff7b72function Te6edf3formatFieldValueForInputTb4b4b4(Te6edf3fieldTb4b4b4, Te6edf3valueTb4b4b4)Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3value Tff7b72== Tff7b72nullTb4b4b4) Tff7b72return Ta5d6ff''Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3fieldTb4b4b4.Te6edf3type Tff7b72=== Te6edf3FTTb4b4b4.Te6edf3BytesTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3value Tff7b72instanceof Tffa657Uint8ArrayTb4b4b4) Tff7b72return Tffa657ArrayTb4b4b4.Tff7b72fromTb4b4b4(Te6edf3valueTb4b4b4)Tb4b4b4.Te6edf3mapTb4b4b4(Te6edf3b Tb4b4b4=> Te6edf3bTb4b4b4.Te6edf3toStringTb4b4b4(T79c0ff16Tb4b4b4)Tb4b4b4.Te6edf3padStartTb4b4b4(T79c0ff2Tb4b4b4, Ta5d6ff'0'Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3joinTb4b4b4(Ta5d6ff''Tb4b4b4)Tb4b4b4;
Tff7b72return Ta5d6ff''Tb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3fieldTb4b4b4.Te6edf3type Tff7b72=== Te6edf3FTTb4b4b4.Te6edf3BytesListTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Tffa657ArrayTb4b4b4.Te6edf3isArrayTb4b4b4(Te6edf3valueTb4b4b4)Tb4b4b4) Tff7b72return Ta5d6ff''Tb4b4b4;
Tff7b72return Te6edf3valueTb4b4b4.Te6edf3mapTb4b4b4(Te6edf3e Tb4b4b4=> Te6edf3e Tff7b72instanceof Tffa657Uint8Array
Tff7b72? Tffa657ArrayTb4b4b4.Tff7b72fromTb4b4b4(Te6edf3eTb4b4b4)Tb4b4b4.Te6edf3mapTb4b4b4(Te6edf3b Tb4b4b4=> Te6edf3bTb4b4b4.Te6edf3toStringTb4b4b4(T79c0ff16Tb4b4b4)Tb4b4b4.Te6edf3padStartTb4b4b4(T79c0ff2Tb4b4b4, Ta5d6ff'0'Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3joinTb4b4b4(Ta5d6ff''Tb4b4b4)
Tff7b72: Ta5d6ff''Tb4b4b4)Tb4b4b4.Te6edf3joinTb4b4b4(Ta5d6ff'\n'Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72return Tffa657StringTb4b4b4(Te6edf3valueTb4b4b4)Tb4b4b4;
Tb4b4b4}

T8b949e// Parse a multi-line hex string into an array of Uint8Array. One entry per
T8b949e// non-blank line; whitespace within a line is stripped (so users can paste
T8b949e// hex with separators). Lines with odd length are rejected by returning null
T8b949e// so the caller can hold off updating the draft until the user finishes typing.
Tff7b72function Te6edf3parseBytesListHexTb4b4b4(Te6edf3textTb4b4b4)Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3text Tff7b72== Tff7b72null Tff7b72|| Te6edf3text Tff7b72=== Ta5d6ff''Tb4b4b4) Tff7b72return Tb4b4b4[Tb4b4b4]Tb4b4b4;
Tff7b72const Te6edf3out Tff7b72= Tb4b4b4[Tb4b4b4]Tb4b4b4;
Tff7b72const Te6edf3lines Tff7b72= Tffa657StringTb4b4b4(Te6edf3textTb4b4b4)Tb4b4b4.Te6edf3splitTb4b4b4(Ta5d6ff/\r?\n/Tb4b4b4)Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3raw Tff7b72of Te6edf3linesTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3h Tff7b72= Te6edf3rawTb4b4b4.Te6edf3replaceTb4b4b4(Ta5d6ff/[^0-9a-fA-F]/gTb4b4b4, Ta5d6ff''Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3hTb4b4b4.Te6edf3length Tff7b72=== T79c0ff0Tb4b4b4) Tff7b72continueTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3hTb4b4b4.Te6edf3length Tff7b72% T79c0ff2 Tff7b72!== T79c0ff0Tb4b4b4) Tff7b72return Tff7b72nullTb4b4b4; T8b949e// not finished typing this line
Tff7b72const Te6edf3u Tff7b72= Tff7b72new Tffa657Uint8ArrayTb4b4b4(Te6edf3hTb4b4b4.Te6edf3length Tff7b72/ T79c0ff2Tb4b4b4)Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72let Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< Te6edf3uTb4b4b4.Te6edf3lengthTb4b4b4; Tff7b72++Te6edf3iTb4b4b4) Te6edf3uTb4b4b4[Te6edf3iTb4b4b4] Tff7b72= Tffa657parseIntTb4b4b4(Te6edf3hTb4b4b4.Te6edf3substrTb4b4b4(Te6edf3iTff7b72*T79c0ff2Tb4b4b4, T79c0ff2Tb4b4b4)Tb4b4b4, T79c0ff16Tb4b4b4)Tb4b4b4;
Te6edf3outTb4b4b4.Te6edf3pushTb4b4b4(Te6edf3uTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72return Te6edf3outTb4b4b4;
Tb4b4b4}

T8b949e// Format a value for display in a read-only / info field. Returns { text, empty }.
T8b949e// `empty` flags styling for "no value yet".
Tff7b72function Te6edf3renderReadOnlyValueTb4b4b4(Te6edf3fTb4b4b4, Te6edf3valueTb4b4b4)Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3value Tff7b72== Tff7b72nullTb4b4b4) Tff7b72return Tb4b4b4{ Te6edf3textTff7b72: Ta5d6ff'—'Tb4b4b4, Te6edf3emptyTff7b72: Tff7b72true Tb4b4b4}Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3fTb4b4b4.Te6edf3type Tff7b72=== Te6edf3FTTb4b4b4.Te6edf3BoolTb4b4b4) Tff7b72return Tb4b4b4{ Te6edf3textTff7b72: Te6edf3value Tff7b72? Ta5d6ff'✓ true' Tff7b72: Ta5d6ff'✗ false'Tb4b4b4, Te6edf3emptyTff7b72: Tff7b72false Tb4b4b4}Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3fTb4b4b4.Te6edf3type Tff7b72=== Te6edf3FTTb4b4b4.Te6edf3EnumTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tffa657ArrayTb4b4b4.Te6edf3isArrayTb4b4b4(Te6edf3fTb4b4b4.Te6edf3enumValuesTb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3idx Tff7b72= Te6edf3fTb4b4b4.Te6edf3enumValuesTb4b4b4.Te6edf3findIndexTb4b4b4(Te6edf3v Tb4b4b4=> Tffa657NumberTb4b4b4(Te6edf3vTb4b4b4) Tff7b72=== Tffa657NumberTb4b4b4(Te6edf3valueTb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3idx Tff7b72>= T79c0ff0 Tff7b72&& Tffa657ArrayTb4b4b4.Te6edf3isArrayTb4b4b4(Te6edf3fTb4b4b4.Te6edf3enumLabelsTb4b4b4) Tff7b72&& Te6edf3fTb4b4b4.Te6edf3enumLabelsTb4b4b4[Te6edf3idxTb4b4b4]Tb4b4b4) Tb4b4b4{
Tff7b72return Tb4b4b4{ Te6edf3textTff7b72: Ta5d6ff`Tffd700${Te6edf3fTb4b4b4.Te6edf3enumLabelsTb4b4b4[Te6edf3idxTb4b4b4]Tffd700}Ta5d6ff (Tffd700${Te6edf3valueTffd700}Ta5d6ff)Ta5d6ff`Tb4b4b4, Te6edf3emptyTff7b72: Tff7b72false Tb4b4b4}Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72return Tb4b4b4{ Te6edf3textTff7b72: Tffa657StringTb4b4b4(Te6edf3valueTb4b4b4)Tb4b4b4, Te6edf3emptyTff7b72: Tff7b72false Tb4b4b4}Tb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3fTb4b4b4.Te6edf3type Tff7b72=== Te6edf3FTTb4b4b4.Te6edf3BytesTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3value Tff7b72instanceof Tffa657Uint8ArrayTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3valueTb4b4b4.Te6edf3length Tff7b72=== T79c0ff0Tb4b4b4) Tff7b72return Tb4b4b4{ Te6edf3textTff7b72: Ta5d6ff'(empty)'Tb4b4b4, Te6edf3emptyTff7b72: Tff7b72true Tb4b4b4}Tb4b4b4;
Tff7b72return Tb4b4b4{ Te6edf3textTff7b72: Tffa657ArrayTb4b4b4.Tff7b72fromTb4b4b4(Te6edf3valueTb4b4b4)Tb4b4b4.Te6edf3mapTb4b4b4(Te6edf3b Tb4b4b4=> Te6edf3bTb4b4b4.Te6edf3toStringTb4b4b4(T79c0ff16Tb4b4b4)Tb4b4b4.Te6edf3padStartTb4b4b4(T79c0ff2Tb4b4b4,Ta5d6ff'0'Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3joinTb4b4b4(Ta5d6ff''Tb4b4b4)Tb4b4b4, Te6edf3emptyTff7b72: Tff7b72false Tb4b4b4}Tb4b4b4;
Tb4b4b4}
Tff7b72return Tb4b4b4{ Te6edf3textTff7b72: Ta5d6ff'—'Tb4b4b4, Te6edf3emptyTff7b72: Tff7b72true Tb4b4b4}Tb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3fTb4b4b4.Te6edf3type Tff7b72=== Te6edf3FTTb4b4b4.Te6edf3BytesListTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tffa657ArrayTb4b4b4.Te6edf3isArrayTb4b4b4(Te6edf3valueTb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3valueTb4b4b4.Te6edf3length Tff7b72=== T79c0ff0Tb4b4b4) Tff7b72return Tb4b4b4{ Te6edf3textTff7b72: Ta5d6ff'(empty list)'Tb4b4b4, Te6edf3emptyTff7b72: Tff7b72true Tb4b4b4}Tb4b4b4;
Tff7b72return Tb4b4b4{ Te6edf3textTff7b72: Te6edf3valueTb4b4b4.Te6edf3mapTb4b4b4(Te6edf3e Tb4b4b4=> Te6edf3e Tff7b72instanceof Tffa657Uint8Array
Tff7b72? Tffa657ArrayTb4b4b4.Tff7b72fromTb4b4b4(Te6edf3eTb4b4b4)Tb4b4b4.Te6edf3mapTb4b4b4(Te6edf3b Tb4b4b4=> Te6edf3bTb4b4b4.Te6edf3toStringTb4b4b4(T79c0ff16Tb4b4b4)Tb4b4b4.Te6edf3padStartTb4b4b4(T79c0ff2Tb4b4b4,Ta5d6ff'0'Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3joinTb4b4b4(Ta5d6ff''Tb4b4b4) Tff7b72: Ta5d6ff''Tb4b4b4)Tb4b4b4.Te6edf3joinTb4b4b4(Ta5d6ff'\n'Tb4b4b4)Tb4b4b4, Te6edf3emptyTff7b72: Tff7b72false Tb4b4b4}Tb4b4b4;
Tb4b4b4}
Tff7b72return Tb4b4b4{ Te6edf3textTff7b72: Ta5d6ff'—'Tb4b4b4, Te6edf3emptyTff7b72: Tff7b72true Tb4b4b4}Tb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3fTb4b4b4.Te6edf3unitTb4b4b4) Tff7b72return Tb4b4b4{ Te6edf3textTff7b72: Ta5d6ff`Tffd700${Te6edf3valueTffd700}Ta5d6ff Tffd700${Te6edf3fTb4b4b4.Te6edf3unitTffd700}Ta5d6ff`Tb4b4b4, Te6edf3emptyTff7b72: Tff7b72false Tb4b4b4}Tb4b4b4;
Tff7b72return Tb4b4b4{ Te6edf3textTff7b72: Tffa657StringTb4b4b4(Te6edf3valueTb4b4b4)Tb4b4b4, Te6edf3emptyTff7b72: Tff7b72false Tb4b4b4}Tb4b4b4;
Tb4b4b4}

T8b949e// Read-only info field: render a static value display (not a disabled input).
T8b949e// Value comes from the server's getter via GET_STATE; we read from committed.
T8b949e// Never participates in nsState.draft, never gates Save.
T8b949e// Shared by all three field-row builders: skeleton row with label + badges
T8b949e// container. Caller decides what trailing controls / value-display to add.
Tff7b72function Te6edf3_buildFieldHeaderTb4b4b4(Te6edf3fTb4b4b4, Te6edf3rowClassTb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3row Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Te6edf3rowClass Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3labelEl Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'label'Tb4b4b4)Tb4b4b4;
Te6edf3labelElTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'span'Tb4b4b4, Tff7b72nullTb4b4b4, Te6edf3fTb4b4b4.Te6edf3label Tff7b72|| Te6edf3fTb4b4b4.Te6edf3nameTb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3badges Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'span'Tb4b4b4, Tb4b4b4{ Te6edf3styleTff7b72: Tb4b4b4{ Te6edf3displayTff7b72: Ta5d6ff'inline-flex'Tb4b4b4, Te6edf3gapTff7b72: Ta5d6ff'4px' Tb4b4b4} Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3labelElTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3badgesTb4b4b4)Tb4b4b4;
Te6edf3rowTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3labelElTb4b4b4)Tb4b4b4;
Tff7b72return Tb4b4b4{ Te6edf3rowTb4b4b4, Te6edf3labelElTb4b4b4, Te6edf3badges Tb4b4b4}Tb4b4b4;
Tb4b4b4}

T8b949e// Construct the input element for a field's declared type. Returns the input
T8b949e// plus a readValue() that extracts the current typed value. Hex / BytesList
T8b949e// readValue may return `{__error: 'reason'}` when the user is mid-edit and the
T8b949e// content isn't a valid byte sequence — callers decide whether to surface the
T8b949e// error (write-only on Send) or silently wait (regular field while typing).
T8b949e//
T8b949e// `opts.secret` makes string inputs render as <input type="password">.
T8b949e// `opts.bigBytesList` switches the BytesList textarea to the larger 5-row
T8b949e// layout used by the regular draft store (vs. the 3-row layout used by the
T8b949e// one-shot write-only form).
Tff7b72function Te6edf3_buildFieldInputTb4b4b4(Te6edf3fTb4b4b4, Te6edf3optsTb4b4b4)Tb4b4b4{
Te6edf3opts Tff7b72= Te6edf3opts Tff7b72|| Tb4b4b4{Tb4b4b4}Tb4b4b4;
Tff7b72const Te6edf3secret Tff7b72= Tff7b72!Tff7b72!Te6edf3optsTb4b4b4.Te6edf3secretTb4b4b4;
Tff7b72const Te6edf3bigBytesList Tff7b72= Tff7b72!Tff7b72!Te6edf3optsTb4b4b4.Te6edf3bigBytesListTb4b4b4;
Tff7b72let Te6edf3inputTb4b4b4;
Tff7b72let Te6edf3readValueTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3fTb4b4b4.Te6edf3type Tff7b72=== Te6edf3FTTb4b4b4.Te6edf3BoolTb4b4b4) Tb4b4b4{
Te6edf3input Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'input'Tb4b4b4, Tb4b4b4{ Te6edf3typeTff7b72: Ta5d6ff'checkbox' Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3readValue Tff7b72= Tb4b4b4(Tb4b4b4) Tb4b4b4=> Te6edf3inputTb4b4b4.Te6edf3checkedTb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3fTb4b4b4.Te6edf3type Tff7b72=== Te6edf3FTTb4b4b4.Te6edf3IntTb4b4b4) Tb4b4b4{
Te6edf3input Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'input'Tb4b4b4, Tb4b4b4{ Te6edf3typeTff7b72: Ta5d6ff'number'Tb4b4b4, Te6edf3stepTff7b72: Ta5d6ff'1'Tb4b4b4,
Te6edf3minTff7b72: Te6edf3fTb4b4b4.Te6edf3minI Tff7b72!= Tff7b72null Tff7b72? Tffa657NumberTb4b4b4(Te6edf3fTb4b4b4.Te6edf3minITb4b4b4) Tff7b72: Tff7b72undefinedTb4b4b4,
Te6edf3maxTff7b72: Te6edf3fTb4b4b4.Te6edf3maxI Tff7b72!= Tff7b72null Tff7b72? Tffa657NumberTb4b4b4(Te6edf3fTb4b4b4.Te6edf3maxITb4b4b4) Tff7b72: Tff7b72undefined Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3readValue Tff7b72= Tb4b4b4(Tb4b4b4) Tb4b4b4=> Te6edf3inputTb4b4b4.Te6edf3value Tff7b72=== Ta5d6ff'' Tff7b72? Tff7b72null Tff7b72: Tffa657parseIntTb4b4b4(Te6edf3inputTb4b4b4.Te6edf3valueTb4b4b4, T79c0ff10Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3fTb4b4b4.Te6edf3type Tff7b72=== Te6edf3FTTb4b4b4.Te6edf3FloatTb4b4b4) Tb4b4b4{
Te6edf3input Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'input'Tb4b4b4, Tb4b4b4{ Te6edf3typeTff7b72: Ta5d6ff'number'Tb4b4b4, Te6edf3stepTff7b72: Ta5d6ff'any'Tb4b4b4,
Te6edf3minTff7b72: Te6edf3fTb4b4b4.Te6edf3minF Tff7b72!= Tff7b72null Tff7b72? Tffa657NumberTb4b4b4(Te6edf3fTb4b4b4.Te6edf3minFTb4b4b4) Tff7b72: Tff7b72undefinedTb4b4b4,
Te6edf3maxTff7b72: Te6edf3fTb4b4b4.Te6edf3maxF Tff7b72!= Tff7b72null Tff7b72? Tffa657NumberTb4b4b4(Te6edf3fTb4b4b4.Te6edf3maxFTb4b4b4) Tff7b72: Tff7b72undefined Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3readValue Tff7b72= Tb4b4b4(Tb4b4b4) Tb4b4b4=> Te6edf3inputTb4b4b4.Te6edf3value Tff7b72=== Ta5d6ff'' Tff7b72? Tff7b72null Tff7b72: Tffa657parseFloatTb4b4b4(Te6edf3inputTb4b4b4.Te6edf3valueTb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3fTb4b4b4.Te6edf3type Tff7b72=== Te6edf3FTTb4b4b4.Tffa657StringTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3big Tff7b72= Te6edf3fTb4b4b4.Te6edf3maxLen Tff7b72&& Tffa657NumberTb4b4b4(Te6edf3fTb4b4b4.Te6edf3maxLenTb4b4b4) Tff7b72> T79c0ff80Tb4b4b4;
Te6edf3input Tff7b72= Te6edf3big
Tff7b72? Te6edf3elTb4b4b4(Ta5d6ff'textarea'Tb4b4b4, Tb4b4b4{ Te6edf3rowsTff7b72: Ta5d6ff'3'Tb4b4b4, Te6edf3maxlengthTff7b72: Tffa657NumberTb4b4b4(Te6edf3fTb4b4b4.Te6edf3maxLenTb4b4b4) Tb4b4b4}Tb4b4b4)
Tff7b72: Te6edf3elTb4b4b4(Ta5d6ff'input'Tb4b4b4, Tb4b4b4{ Te6edf3typeTff7b72: Te6edf3secret Tff7b72? Ta5d6ff'password' Tff7b72: Ta5d6ff'text'Tb4b4b4, Te6edf3maxlengthTff7b72: Te6edf3fTb4b4b4.Te6edf3maxLen Tff7b72? Tffa657NumberTb4b4b4(Te6edf3fTb4b4b4.Te6edf3maxLenTb4b4b4) Tff7b72: Tff7b72undefined Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3readValue Tff7b72= Tb4b4b4(Tb4b4b4) Tb4b4b4=> Te6edf3inputTb4b4b4.Te6edf3valueTb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3fTb4b4b4.Te6edf3type Tff7b72=== Te6edf3FTTb4b4b4.Te6edf3EnumTb4b4b4) Tb4b4b4{
Te6edf3input Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'select'Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tffa657ArrayTb4b4b4.Te6edf3isArrayTb4b4b4(Te6edf3fTb4b4b4.Te6edf3enumValuesTb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3labels Tff7b72= Tffa657ArrayTb4b4b4.Te6edf3isArrayTb4b4b4(Te6edf3fTb4b4b4.Te6edf3enumLabelsTb4b4b4) Tff7b72? Te6edf3fTb4b4b4.Te6edf3enumLabels Tff7b72: Tff7b72nullTb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72let Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< Te6edf3fTb4b4b4.Te6edf3enumValuesTb4b4b4.Te6edf3lengthTb4b4b4; Tff7b72++Te6edf3iTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3ev Tff7b72= Tffa657NumberTb4b4b4(Te6edf3fTb4b4b4.Te6edf3enumValuesTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4)Tb4b4b4;
Te6edf3inputTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'option'Tb4b4b4, Tb4b4b4{ Te6edf3valueTff7b72: Tffa657StringTb4b4b4(Te6edf3evTb4b4b4) Tb4b4b4}Tb4b4b4, Te6edf3labels Tff7b72&& Te6edf3labelsTb4b4b4[Te6edf3iTb4b4b4] Tff7b72? Te6edf3labelsTb4b4b4[Te6edf3iTb4b4b4] Tff7b72: Tffa657StringTb4b4b4(Te6edf3evTb4b4b4)Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Te6edf3readValue Tff7b72= Tb4b4b4(Tb4b4b4) Tb4b4b4=> Te6edf3inputTb4b4b4.Te6edf3value Tff7b72=== Ta5d6ff'' Tff7b72? Tff7b72null Tff7b72: Tffa657parseIntTb4b4b4(Te6edf3inputTb4b4b4.Te6edf3valueTb4b4b4, T79c0ff10Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3fTb4b4b4.Te6edf3type Tff7b72=== Te6edf3FTTb4b4b4.Te6edf3BytesTb4b4b4) Tb4b4b4{
Te6edf3input Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'input'Tb4b4b4, Tb4b4b4{ Te6edf3typeTff7b72: Ta5d6ff'text'Tb4b4b4, Te6edf3placeholderTff7b72: Te6edf3fTb4b4b4.Te6edf3maxLen Tff7b72? Ta5d6ff`Ta5d6ffhex (max Tffd700${Te6edf3fTb4b4b4.Te6edf3maxLenTffd700}Ta5d6ff bytes)Ta5d6ff` Tff7b72: Ta5d6ff'hex' Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3readValue Tff7b72= Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3t Tff7b72= Tffa657StringTb4b4b4(Te6edf3inputTb4b4b4.Te6edf3value Tff7b72|| Ta5d6ff''Tb4b4b4)Tb4b4b4.Te6edf3replaceTb4b4b4(Ta5d6ff/[^0-9a-fA-F]/gTb4b4b4, Ta5d6ff''Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3tTb4b4b4.Te6edf3length Tff7b72% T79c0ff2 Tff7b72!== T79c0ff0Tb4b4b4) Tff7b72return Tb4b4b4{ Te6edf3__errorTff7b72: Ta5d6ff'odd hex' Tb4b4b4}Tb4b4b4;
Tff7b72const Te6edf3u8 Tff7b72= Tff7b72new Tffa657Uint8ArrayTb4b4b4(Te6edf3tTb4b4b4.Te6edf3length Tff7b72/ T79c0ff2Tb4b4b4)Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72let Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< Te6edf3u8Tb4b4b4.Te6edf3lengthTb4b4b4; Tff7b72++Te6edf3iTb4b4b4) Te6edf3u8Tb4b4b4[Te6edf3iTb4b4b4] Tff7b72= Tffa657parseIntTb4b4b4(Te6edf3tTb4b4b4.Te6edf3substrTb4b4b4(Te6edf3iTff7b72*T79c0ff2Tb4b4b4, T79c0ff2Tb4b4b4)Tb4b4b4, T79c0ff16Tb4b4b4)Tb4b4b4;
Tff7b72return Te6edf3u8Tb4b4b4;
Tb4b4b4}Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3fTb4b4b4.Te6edf3type Tff7b72=== Te6edf3FTTb4b4b4.Te6edf3BytesListTb4b4b4) Tb4b4b4{
T8b949e// One hex entry per line. elementSize fixes per-entry length; maxCount
T8b949e// limits total entries. Both are zero/null when unconstrained.
Tff7b72const Te6edf3sz Tff7b72= Te6edf3fTb4b4b4.Te6edf3elementSize Tff7b72!= Tff7b72null Tff7b72? Tffa657NumberTb4b4b4(Te6edf3fTb4b4b4.Te6edf3elementSizeTb4b4b4) Tff7b72: T79c0ff0Tb4b4b4;
Tff7b72const Te6edf3max Tff7b72= Te6edf3fTb4b4b4.Te6edf3maxCount Tff7b72!= Tff7b72null Tff7b72? Tffa657NumberTb4b4b4(Te6edf3fTb4b4b4.Te6edf3maxCountTb4b4b4) Tff7b72: T79c0ff0Tb4b4b4;
Tff7b72const Te6edf3hints Tff7b72= Tb4b4b4[Tb4b4b4]Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sz Tff7b72> T79c0ff0Tb4b4b4) Te6edf3hintsTb4b4b4.Te6edf3pushTb4b4b4(Te6edf3bigBytesList Tff7b72? Ta5d6ff`Tffd700${Te6edf3szTffd700}Ta5d6ff bytes / Tffd700${Te6edf3szTff7b72*T79c0ff2Tffd700}Ta5d6ff hex chars per entryTa5d6ff` Tff7b72: Ta5d6ff`Tffd700${Te6edf3szTffd700}Ta5d6ff bytes per entryTa5d6ff`Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3max Tff7b72> T79c0ff0Tb4b4b4) Te6edf3hintsTb4b4b4.Te6edf3pushTb4b4b4(Ta5d6ff`Ta5d6ffup to Tffd700${Te6edf3maxTffd700}Ta5d6ff entriesTa5d6ff`Tb4b4b4)Tb4b4b4;
Te6edf3hintsTb4b4b4.Te6edf3pushTb4b4b4(Ta5d6ff'one per line'Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3style Tff7b72= Te6edf3bigBytesList
Tff7b72? Tb4b4b4{ Te6edf3fontFamilyTff7b72: Ta5d6ff'ui-monospace, Menlo, monospace'Tb4b4b4, Te6edf3minWidthTff7b72: Ta5d6ff'360px' Tb4b4b4}
Tff7b72: Tb4b4b4{ Te6edf3fontFamilyTff7b72: Ta5d6ff'ui-monospace, Menlo, monospace' Tb4b4b4}Tb4b4b4;
Te6edf3input Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'textarea'Tb4b4b4, Tb4b4b4{ Te6edf3rowsTff7b72: Te6edf3bigBytesList Tff7b72? Ta5d6ff'5' Tff7b72: Ta5d6ff'3'Tb4b4b4, Te6edf3placeholderTff7b72: Ta5d6ff'hex (' Tff7b72+ Te6edf3hintsTb4b4b4.Te6edf3joinTb4b4b4(Ta5d6ff', 'Tb4b4b4) Tff7b72+ Ta5d6ff')'Tb4b4b4, Te6edf3style Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3readValue Tff7b72= Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3list Tff7b72= Te6edf3parseBytesListHexTb4b4b4(Te6edf3inputTb4b4b4.Te6edf3valueTb4b4b4)Tb4b4b4;
T8b949e// null = an in-progress odd-length line. Callers in the regular draft
T8b949e// path treat this as "wait" (silent no-op); the WO path surfaces it on
T8b949e// Send so the user knows why nothing happened.
Tff7b72if Tb4b4b4(Te6edf3list Tff7b72== Tff7b72nullTb4b4b4) Tff7b72return Tb4b4b4{ Te6edf3__errorTff7b72: Ta5d6ff'odd hex on one of the lines' Tb4b4b4}Tb4b4b4;
Tff7b72return Te6edf3listTb4b4b4;
Tb4b4b4}Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3fTb4b4b4.Te6edf3type Tff7b72=== Te6edf3FTTb4b4b4.Te6edf3VoidTb4b4b4) Tb4b4b4{
T8b949e// Argument-less command — the Send button is the entire control surface.
Te6edf3input Tff7b72= Tff7b72nullTb4b4b4;
Te6edf3readValue Tff7b72= Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tff7b72nullTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3input Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'span'Tb4b4b4, Tff7b72nullTb4b4b4, Ta5d6ff'(unknown type)'Tb4b4b4)Tb4b4b4;
Te6edf3readValue Tff7b72= Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tff7b72nullTb4b4b4;
Tb4b4b4}
Tff7b72return Tb4b4b4{ Te6edf3inputTb4b4b4, Te6edf3readValue Tb4b4b4}Tb4b4b4;
Tb4b4b4}

Tff7b72function Te6edf3buildFieldRowReadOnlyTb4b4b4(Te6edf3nsIdTb4b4b4, Te6edf3fTb4b4b4, Te6edf3cTb4b4b4)Tb4b4b4{
Tff7b72const Tb4b4b4{ Te6edf3rowTb4b4b4, Te6edf3badges Tb4b4b4} Tff7b72= Te6edf3_buildFieldHeaderTb4b4b4(Te6edf3fTb4b4b4, Ta5d6ff'field ro-info'Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3valueEl Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'ro-value' Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3rowTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3valueElTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3secret Tff7b72= Tff7b72!Tff7b72!Tb4b4b4(Te6edf3fTb4b4b4.Te6edf3flags Tff7b72& Te6edf3FFTb4b4b4.Te6edf3SECRETTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3reboot Tff7b72= Tff7b72!Tff7b72!Tb4b4b4(Te6edf3fTb4b4b4.Te6edf3flags Tff7b72& Te6edf3FFTb4b4b4.Te6edf3REBOOT_REQUIREDTb4b4b4)Tb4b4b4;
Tff7b72function Te6edf3updateTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3nsObj Tff7b72= Te6edf3cTb4b4b4.Te6edf3stateTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4[Te6edf3nsIdTb4b4b4] Tff7b72|| Tb4b4b4{ Te6edf3committedTff7b72: Tb4b4b4{Tb4b4b4}Tb4b4b4, Te6edf3draftTff7b72: Tb4b4b4{Tb4b4b4} Tb4b4b4}Tb4b4b4;
T8b949e// FF_SECRET fields aren't returned in GET_STATE, so committed will be empty.
Tff7b72const Te6edf3value Tff7b72= Tb4b4b4(Te6edf3fTb4b4b4.Te6edf3id Tff7b72in Te6edf3nsObjTb4b4b4.Te6edf3committedTb4b4b4) Tff7b72? Te6edf3nsObjTb4b4b4.Te6edf3committedTb4b4b4[Te6edf3fTb4b4b4.Te6edf3idTb4b4b4] Tff7b72: Tff7b72nullTb4b4b4;
Tff7b72const Te6edf3rendered Tff7b72= Te6edf3secret Tff7b72&& Te6edf3value Tff7b72== Tff7b72null
Tff7b72? Tb4b4b4{ Te6edf3textTff7b72: Ta5d6ff'(secret — not exposed)'Tb4b4b4, Te6edf3emptyTff7b72: Tff7b72true Tb4b4b4}
Tff7b72: Te6edf3renderReadOnlyValueTb4b4b4(Te6edf3fTb4b4b4, Te6edf3valueTb4b4b4)Tb4b4b4;
Te6edf3valueElTb4b4b4.Te6edf3textContent Tff7b72= Te6edf3renderedTb4b4b4.Te6edf3textTb4b4b4;
Te6edf3valueElTb4b4b4.Te6edf3classListTb4b4b4.Te6edf3toggleTb4b4b4(Ta5d6ff'empty'Tb4b4b4, Te6edf3renderedTb4b4b4.Te6edf3emptyTb4b4b4)Tb4b4b4;
Te6edf3badgesTb4b4b4.Te6edf3innerHTML Tff7b72= Ta5d6ff''Tb4b4b4;
Te6edf3badgesTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'span'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'badge ro' Tb4b4b4}Tb4b4b4, Ta5d6ff'read-only'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3secretTb4b4b4) Te6edf3badgesTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'span'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'badge secret' Tb4b4b4}Tb4b4b4, Ta5d6ff'secret'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3rebootTb4b4b4) Te6edf3badgesTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'span'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'badge reboot' Tb4b4b4}Tb4b4b4, Ta5d6ff'↻ reboot'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3updateTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72return Tb4b4b4{ Te6edf3rowTb4b4b4, Te6edf3updateTb4b4b4, Te6edf3fieldIdTff7b72: Te6edf3fTb4b4b4.Te6edf3idTb4b4b4, Te6edf3hasDraftErrorTff7b72: Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tff7b72false Tb4b4b4}Tb4b4b4;
Tb4b4b4}

T8b949e// Write-only command field: input + Send button. Send fires SetState+Commit
T8b949e// for this single field. Value isn't stored in nsState.draft and the field
T8b949e// doesn't gate Save / Revert / Commit-all.
Tff7b72function Te6edf3buildFieldRowWriteOnlyTb4b4b4(Te6edf3nsIdTb4b4b4, Te6edf3fTb4b4b4, Te6edf3cTb4b4b4)Tb4b4b4{
Tff7b72const Tb4b4b4{ Te6edf3rowTb4b4b4, Te6edf3badges Tb4b4b4} Tff7b72= Te6edf3_buildFieldHeaderTb4b4b4(Te6edf3fTb4b4b4, Ta5d6ff'field wo-action'Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3controls Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'wo-controls' Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3errEl Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'err' Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3rowTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3controlsTb4b4b4)Tb4b4b4;
Te6edf3rowTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3errElTb4b4b4)Tb4b4b4;

Tff7b72const Te6edf3secret Tff7b72= Tff7b72!Tff7b72!Tb4b4b4(Te6edf3fTb4b4b4.Te6edf3flags Tff7b72& Te6edf3FFTb4b4b4.Te6edf3SECRETTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3reboot Tff7b72= Tff7b72!Tff7b72!Tb4b4b4(Te6edf3fTb4b4b4.Te6edf3flags Tff7b72& Te6edf3FFTb4b4b4.Te6edf3REBOOT_REQUIREDTb4b4b4)Tb4b4b4;

T8b949e// WO fields have no draft store — the live input value is read directly
T8b949e// on Send. _buildFieldInput's readValue() returns {__error} for unparseable
T8b949e// hex/bytes-list content, which we surface in errEl below.
Tff7b72const Tb4b4b4{ Te6edf3inputTb4b4b4, Te6edf3readValue Tb4b4b4} Tff7b72= Te6edf3_buildFieldInputTb4b4b4(Te6edf3fTb4b4b4, Tb4b4b4{ Te6edf3secretTb4b4b4, Te6edf3bigBytesListTff7b72: Tff7b72false Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3inputTb4b4b4) Te6edf3controlsTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3inputTb4b4b4)Tb4b4b4; T8b949e// FT.Void has no input element.

Tff7b72const Te6edf3sendBtn Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'button'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'wo-send' Tb4b4b4}Tb4b4b4, Ta5d6ff'Send'Tb4b4b4)Tb4b4b4;
Te6edf3controlsTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3sendBtnTb4b4b4)Tb4b4b4;

Te6edf3sendBtnTb4b4b4.Te6edf3onclick Tff7b72= Tff7b72async Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3clientTb4b4b4) Tb4b4b4{ Te6edf3showToastTb4b4b4(Ta5d6ff'Not connected'Tb4b4b4, Ta5d6ff'err'Tb4b4b4)Tb4b4b4; Tff7b72returnTb4b4b4; Tb4b4b4}
Tff7b72const Te6edf3v Tff7b72= Te6edf3readValueTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3v Tff7b72&& Tff7b72typeof Te6edf3v Tff7b72=== Ta5d6ff'object' Tff7b72&& Ta5d6ff'__error' Tff7b72in Te6edf3vTb4b4b4) Tb4b4b4{
Te6edf3errElTb4b4b4.Te6edf3textContent Tff7b72= Te6edf3vTb4b4b4.Te6edf3__errorTb4b4b4; Te6edf3rowTb4b4b4.Te6edf3classListTb4b4b4.Te6edf3addTb4b4b4(Ta5d6ff'has-err'Tb4b4b4)Tb4b4b4; Tff7b72returnTb4b4b4;
Tb4b4b4}
Tff7b72const Te6edf3verr Tff7b72= Te6edf3validateValueTb4b4b4(Te6edf3fTb4b4b4, Te6edf3vTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3verrTb4b4b4) Tb4b4b4{ Te6edf3errElTb4b4b4.Te6edf3textContent Tff7b72= Te6edf3verrTb4b4b4; Te6edf3rowTb4b4b4.Te6edf3classListTb4b4b4.Te6edf3addTb4b4b4(Ta5d6ff'has-err'Tb4b4b4)Tb4b4b4; Tff7b72returnTb4b4b4; Tb4b4b4}
Te6edf3errElTb4b4b4.Te6edf3textContent Tff7b72= Ta5d6ff''Tb4b4b4; Te6edf3rowTb4b4b4.Te6edf3classListTb4b4b4.Te6edf3removeTb4b4b4(Ta5d6ff'has-err'Tb4b4b4)Tb4b4b4;
T8b949e// Write-only fields are imperative one-shot commands (Clear Storage,
T8b949e// Clear Provisioning, reboots, etc.) that fire setters server-side with
T8b949e// no draft / revert step. Always require an explicit confirmation so a
T8b949e// misclick can't trigger a destructive action.
Tff7b72const Te6edf3label Tff7b72= Te6edf3fTb4b4b4.Te6edf3label Tff7b72|| Te6edf3fTb4b4b4.Te6edf3name Tff7b72|| Ta5d6ff'this command'Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Tffa657windowTb4b4b4.Te6edf3confirmTb4b4b4(Ta5d6ff`Ta5d6ffSend "Tffd700${Te6edf3labelTffd700}Ta5d6ff"?Ta5d6ff\nTa5d6ff\nTa5d6ffThis is a one-shot command and cannot be undone.Ta5d6ff`Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72returnTb4b4b4;
Tb4b4b4}
Te6edf3sendBtnTb4b4b4.Te6edf3disabled Tff7b72= Tff7b72trueTb4b4b4;
Tff7b72const Te6edf3prevLbl Tff7b72= Te6edf3sendBtnTb4b4b4.Te6edf3textContent Tff7b72|| Ta5d6ff'Send'Tb4b4b4;
Te6edf3sendBtnTb4b4b4.Te6edf3textContent Tff7b72= Ta5d6ff'Sending…'Tb4b4b4;
Tff7b72try Tb4b4b4{
T8b949e// SetState puts the value in the firmware's per-field draft (write-only
T8b949e// accepts drafts but doesn't persist). Commit fires the setter once.
Tff7b72const Te6edf3res Tff7b72= Tff7b72await Te6edf3clientTb4b4b4.Te6edf3setStateTb4b4b4(Tb4b4b4{ Tb4b4b4[Te6edf3nsIdTb4b4b4]Tff7b72: Tb4b4b4{ Tb4b4b4[Te6edf3fTb4b4b4.Te6edf3idTb4b4b4]Tff7b72: Tb4b4b4{ Te6edf3typeTff7b72: Te6edf3fTb4b4b4.Te6edf3typeTb4b4b4, Te6edf3valueTff7b72: Te6edf3v Tb4b4b4} Tb4b4b4} Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3resTb4b4b4.Te6edf3fieldErrors Tff7b72&& Te6edf3resTb4b4b4.Te6edf3fieldErrorsTb4b4b4.Te6edf3length Tff7b72> T79c0ff0Tb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3fe Tff7b72= Te6edf3resTb4b4b4.Te6edf3fieldErrorsTb4b4b4.Te6edf3findTb4b4b4(Te6edf3e Tb4b4b4=> Te6edf3eTb4b4b4.Te6edf3ns Tff7b72=== Te6edf3nsId Tff7b72&& Te6edf3eTb4b4b4.Te6edf3field Tff7b72=== Te6edf3fTb4b4b4.Te6edf3idTb4b4b4) Tff7b72|| Te6edf3resTb4b4b4.Te6edf3fieldErrorsTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4;
Te6edf3errElTb4b4b4.Te6edf3textContent Tff7b72= Ta5d6ff'server: ' Tff7b72+ Te6edf3feTb4b4b4.Te6edf3codeNameTb4b4b4;
Te6edf3rowTb4b4b4.Te6edf3classListTb4b4b4.Te6edf3addTb4b4b4(Ta5d6ff'has-err'Tb4b4b4)Tb4b4b4;
Te6edf3showToastTb4b4b4(Ta5d6ff`Ta5d6ffSend rejected: Tffd700${Te6edf3feTb4b4b4.Te6edf3codeNameTffd700}Ta5d6ff`Tb4b4b4, Ta5d6ff'err'Tb4b4b4)Tb4b4b4;
Tff7b72returnTb4b4b4;
Tb4b4b4}
Tff7b72await Te6edf3clientTb4b4b4.Te6edf3commitTb4b4b4(Tb4b4b4[Te6edf3nsIdTb4b4b4]Tb4b4b4)Tb4b4b4;
Te6edf3showToastTb4b4b4(Ta5d6ff`Ta5d6ffSent Tffd700${Te6edf3fTb4b4b4.Te6edf3label Tff7b72|| Te6edf3fTb4b4b4.Te6edf3nameTffd700}Ta5d6ff`Tb4b4b4, Ta5d6ff'ok'Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{
Te6edf3errElTb4b4b4.Te6edf3textContent Tff7b72= Te6edf3eTb4b4b4.Te6edf3message Tff7b72|| Tffa657StringTb4b4b4(Te6edf3eTb4b4b4)Tb4b4b4;
Te6edf3rowTb4b4b4.Te6edf3classListTb4b4b4.Te6edf3addTb4b4b4(Ta5d6ff'has-err'Tb4b4b4)Tb4b4b4;
Te6edf3showToastTb4b4b4(Ta5d6ff`Ta5d6ffSend failed: Tffd700${Te6edf3eTb4b4b4.Te6edf3message Tff7b72|| Te6edf3eTffd700}Ta5d6ff`Tb4b4b4, Ta5d6ff'err'Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72finally Tb4b4b4{
Te6edf3sendBtnTb4b4b4.Te6edf3disabled Tff7b72= Tff7b72falseTb4b4b4;
Te6edf3sendBtnTb4b4b4.Te6edf3textContent Tff7b72= Te6edf3prevLblTb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4;

Tff7b72function Te6edf3updateTb4b4b4(Tb4b4b4)Tb4b4b4{
Te6edf3badgesTb4b4b4.Te6edf3innerHTML Tff7b72= Ta5d6ff''Tb4b4b4;
Te6edf3badgesTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'span'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'badge wo' Tb4b4b4}Tb4b4b4, Ta5d6ff'command'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3secretTb4b4b4) Te6edf3badgesTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'span'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'badge secret' Tb4b4b4}Tb4b4b4, Ta5d6ff'secret'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3rebootTb4b4b4) Te6edf3badgesTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'span'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'badge reboot' Tb4b4b4}Tb4b4b4, Ta5d6ff'↻ reboot'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3updateTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72return Tb4b4b4{ Te6edf3rowTb4b4b4, Te6edf3updateTb4b4b4, Te6edf3fieldIdTff7b72: Te6edf3fTb4b4b4.Te6edf3idTb4b4b4, Te6edf3hasDraftErrorTff7b72: Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tff7b72false Tb4b4b4}Tb4b4b4;
Tb4b4b4}

Tff7b72function Te6edf3buildFieldRowTb4b4b4(Te6edf3nsIdTb4b4b4, Te6edf3fTb4b4b4, Te6edf3ctxTb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3c Tff7b72= Te6edf3_ctxOrTb4b4b4(Te6edf3ctxTb4b4b4)Tb4b4b4;
T8b949e// FF_WRITE_ONLY and FF_READ_ONLY are routed to specialised renderers — they
T8b949e// don't participate in the namespace draft store and they don't gate Save.
Tff7b72const Te6edf3wo Tff7b72= Tff7b72!Tff7b72!Tb4b4b4(Te6edf3fTb4b4b4.Te6edf3flags Tff7b72& Te6edf3FFTb4b4b4.Te6edf3WRITE_ONLYTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3ro Tff7b72= Tff7b72!Tff7b72!Tb4b4b4(Te6edf3fTb4b4b4.Te6edf3flags Tff7b72& Te6edf3FFTb4b4b4.Te6edf3READ_ONLYTb4b4b4) Tff7b72&& Tff7b72!Te6edf3woTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3roTb4b4b4) Tff7b72return Te6edf3buildFieldRowReadOnlyTb4b4b4(Te6edf3nsIdTb4b4b4, Te6edf3fTb4b4b4, Te6edf3cTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3woTb4b4b4) Tff7b72return Te6edf3buildFieldRowWriteOnlyTb4b4b4(Te6edf3nsIdTb4b4b4, Te6edf3fTb4b4b4, Te6edf3cTb4b4b4)Tb4b4b4;
Tff7b72const Tb4b4b4{ Te6edf3rowTb4b4b4, Te6edf3badges Tb4b4b4} Tff7b72= Te6edf3_buildFieldHeaderTb4b4b4(Te6edf3fTb4b4b4, Ta5d6ff'field'Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3inputHost Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3errEl Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'err' Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3rowTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3inputHostTb4b4b4)Tb4b4b4;
Te6edf3rowTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3errElTb4b4b4)Tb4b4b4;

T8b949e// FF_READ_ONLY already routed to buildFieldRowReadOnly above (and FF_WRITE_ONLY
T8b949e// to buildFieldRowWriteOnly), so we never need to disable inputs here.
Tff7b72const Te6edf3secret Tff7b72= Tff7b72!Tff7b72!Tb4b4b4(Te6edf3fTb4b4b4.Te6edf3flags Tff7b72& Te6edf3FFTb4b4b4.Te6edf3SECRETTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3reboot Tff7b72= Tff7b72!Tff7b72!Tb4b4b4(Te6edf3fTb4b4b4.Te6edf3flags Tff7b72& Te6edf3FFTb4b4b4.Te6edf3REBOOT_REQUIREDTb4b4b4)Tb4b4b4;
T8b949e// Legacy Node Config fields with no KISS read counterpart. The displayed
T8b949e// value is a schema placeholder, not a readback — surface this with a badge
T8b949e// so the user doesn't mistake the placeholder for the device's current state.
Tff7b72const Te6edf3setOnly Tff7b72= Tb4b4b4(Te6edf3fTb4b4b4.Te6edf3readable Tff7b72=== Tff7b72falseTb4b4b4)Tb4b4b4;

T8b949e// Build input ONCE; we never recreate it on subsequent state changes. Use
T8b949e// the regular-draft variant (bigBytesList=true) so BytesList textareas get
T8b949e// the larger 5-row / 360px-min layout intended for sustained editing.
Tff7b72const Tb4b4b4{ Te6edf3inputTb4b4b4, Te6edf3readValue Tb4b4b4} Tff7b72= Te6edf3_buildFieldInputTb4b4b4(Te6edf3fTb4b4b4, Tb4b4b4{ Te6edf3secretTb4b4b4, Te6edf3bigBytesListTff7b72: Tff7b72true Tb4b4b4}Tb4b4b4)Tb4b4b4;

T8b949e// Wire the right event to setDraftValue. Most types use 'input' (continuous);
T8b949e// <select> only fires 'change'. Hex/BytesList readValue returns {__error}
T8b949e// mid-edit; we silently skip those so a half-typed value doesn't clobber
T8b949e// the draft (the regular flow waits for the user to finish typing).
Tff7b72const Te6edf3evtName Tff7b72= Tb4b4b4(Te6edf3fTb4b4b4.Te6edf3type Tff7b72=== Te6edf3FTTb4b4b4.Te6edf3EnumTb4b4b4) Tff7b72? Ta5d6ff'change' Tff7b72: Ta5d6ff'input'Tb4b4b4;
Te6edf3inputTb4b4b4.Te6edf3addEventListenerTb4b4b4(Te6edf3evtNameTb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3v Tff7b72= Te6edf3readValueTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3v Tff7b72&& Tff7b72typeof Te6edf3v Tff7b72=== Ta5d6ff'object' Tff7b72&& Ta5d6ff'__error' Tff7b72in Te6edf3vTb4b4b4) Tff7b72returnTb4b4b4;
Te6edf3setDraftValueTb4b4b4(Te6edf3nsIdTb4b4b4, Te6edf3fTb4b4b4, Te6edf3vTb4b4b4, Te6edf3cTb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;
T8b949e// Optional unit suffix (e.g. "Hz", "dBm") rendered next to the input.
Tff7b72if Tb4b4b4(Te6edf3fTb4b4b4.Te6edf3unitTb4b4b4) Tb4b4b4{
Te6edf3inputHostTb4b4b4.Te6edf3styleTb4b4b4.Te6edf3display Tff7b72= Ta5d6ff'flex'Tb4b4b4;
Te6edf3inputHostTb4b4b4.Te6edf3styleTb4b4b4.Te6edf3alignItems Tff7b72= Ta5d6ff'center'Tb4b4b4;
Te6edf3inputHostTb4b4b4.Te6edf3styleTb4b4b4.Te6edf3gap Tff7b72= Ta5d6ff'6px'Tb4b4b4;
Te6edf3inputHostTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3inputTb4b4b4)Tb4b4b4;
Te6edf3inputHostTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'span'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'unit'Tb4b4b4, Te6edf3styleTff7b72: Tb4b4b4{ Te6edf3colorTff7b72: Ta5d6ff'var(--muted)' Tb4b4b4} Tb4b4b4}Tb4b4b4, Te6edf3fTb4b4b4.Te6edf3unitTb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3inputHostTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3inputTb4b4b4)Tb4b4b4;
Tb4b4b4}

Tff7b72function Te6edf3updateTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3nsObj Tff7b72= Te6edf3cTb4b4b4.Te6edf3stateTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4[Te6edf3nsIdTb4b4b4] Tff7b72|| Tb4b4b4{ Te6edf3committedTff7b72: Tb4b4b4{Tb4b4b4}Tb4b4b4, Te6edf3draftTff7b72: Tb4b4b4{Tb4b4b4} Tb4b4b4}Tb4b4b4;
Tff7b72const Te6edf3value Tff7b72= Te6edf3getEffectiveValueTb4b4b4(Te6edf3nsIdTb4b4b4, Te6edf3fTb4b4b4, Te6edf3cTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3isDraft Tff7b72= Te6edf3fTb4b4b4.Te6edf3id Tff7b72in Te6edf3nsObjTb4b4b4.Te6edf3draftTb4b4b4;
T8b949e// Sync input value ONLY if it's not currently focused — preserves cursor/selection while typing.
Tff7b72if Tb4b4b4(Tffa657documentTb4b4b4.Te6edf3activeElement Tff7b72!== Te6edf3inputTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3fTb4b4b4.Te6edf3type Tff7b72=== Te6edf3FTTb4b4b4.Te6edf3BoolTb4b4b4) Tb4b4b4{
Te6edf3inputTb4b4b4.Te6edf3checked Tff7b72= Tff7b72!Tff7b72!Te6edf3valueTb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3fTb4b4b4.Te6edf3type Tff7b72=== Te6edf3FTTb4b4b4.Te6edf3EnumTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3want Tff7b72= Tffa657StringTb4b4b4(Tffa657NumberTb4b4b4(Te6edf3valueTb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3inputTb4b4b4.Te6edf3value Tff7b72!== Te6edf3wantTb4b4b4) Te6edf3inputTb4b4b4.Te6edf3value Tff7b72= Te6edf3wantTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72const Te6edf3fmt Tff7b72= Te6edf3formatFieldValueForInputTb4b4b4(Te6edf3fTb4b4b4, Te6edf3valueTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3inputTb4b4b4.Te6edf3value Tff7b72!== Te6edf3fmtTb4b4b4) Te6edf3inputTb4b4b4.Te6edf3value Tff7b72= Te6edf3fmtTb4b4b4;
Tb4b4b4}
Tb4b4b4}
T8b949e// Badges
Te6edf3badgesTb4b4b4.Te6edf3innerHTML Tff7b72= Ta5d6ff''Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3roTb4b4b4) Te6edf3badgesTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'span'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'badge ro' Tb4b4b4}Tb4b4b4, Ta5d6ff'read-only'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3secretTb4b4b4) Te6edf3badgesTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'span'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'badge secret' Tb4b4b4}Tb4b4b4, Ta5d6ff'secret'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3rebootTb4b4b4) Te6edf3badgesTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'span'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'badge reboot' Tb4b4b4}Tb4b4b4, Ta5d6ff'↻ reboot'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3setOnlyTb4b4b4) Te6edf3badgesTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'span'Tb4b4b4, Tb4b4b4{
Tff7b72classTff7b72: Ta5d6ff'badge set-only'Tb4b4b4,
Te6edf3titleTff7b72: Ta5d6ff'Write-only on this device. The value shown is a schema placeholder; editing and Save writes the value to the device, but the firmware does not expose a read opcode for this field.'
Tb4b4b4}Tb4b4b4, Ta5d6ff'set-only'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3isDraftTb4b4b4) Te6edf3badgesTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'span'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'badge draft' Tb4b4b4}Tb4b4b4, Ta5d6ff'• draft'Tb4b4b4)Tb4b4b4)Tb4b4b4;
T8b949e// Errors — only surface validation errors for fields the user actually edited.
T8b949e// Untouched fields may carry firmware "sentinel" defaults (e.g. radio.frequency=0)
T8b949e// that fall outside the advertised min/max range; the firmware ignores them as
T8b949e// "unconfigured", so we should not flag them as user-facing errors.
Tff7b72const Te6edf3serverErr Tff7b72= Te6edf3cTb4b4b4.Te6edf3errors Tff7b72&& Tb4b4b4(Te6edf3cTb4b4b4.Te6edf3errorsTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4[Te6edf3nsIdTb4b4b4] Tff7b72|| Tb4b4b4{Tb4b4b4}Tb4b4b4)Tb4b4b4[Te6edf3fTb4b4b4.Te6edf3idTb4b4b4]Tb4b4b4;
Tff7b72const Te6edf3valErr Tff7b72= Tb4b4b4(Te6edf3isDraft Tff7b72&& Te6edf3validateValueTb4b4b4(Te6edf3fTb4b4b4, Te6edf3valueTb4b4b4)Tb4b4b4) Tff7b72|| Tff7b72nullTb4b4b4;
Tff7b72const Te6edf3msg Tff7b72= Te6edf3serverErr Tff7b72? Ta5d6ff'server: ' Tff7b72+ Te6edf3serverErr Tff7b72: Te6edf3valErrTb4b4b4;
Te6edf3errElTb4b4b4.Te6edf3textContent Tff7b72= Te6edf3msg Tff7b72|| Ta5d6ff''Tb4b4b4;
Te6edf3rowTb4b4b4.Te6edf3classListTb4b4b4.Te6edf3toggleTb4b4b4(Ta5d6ff'has-err'Tb4b4b4, Tff7b72!Tff7b72!Te6edf3msgTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72return Tb4b4b4{
Te6edf3rowTb4b4b4,
Te6edf3updateTb4b4b4,
Te6edf3fieldIdTff7b72: Te6edf3fTb4b4b4.Te6edf3idTb4b4b4,
T8b949e// hasDraftError: only count validation errors for drafted fields toward
T8b949e// the Save-button gate, for the same reason as the display above.
Te6edf3hasDraftErrorTff7b72: Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3draft Tff7b72= Tb4b4b4(Te6edf3cTb4b4b4.Te6edf3stateTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4[Te6edf3nsIdTb4b4b4] Tff7b72|| Tb4b4b4{Tb4b4b4}Tb4b4b4)Tb4b4b4.Te6edf3draft Tff7b72|| Tb4b4b4{Tb4b4b4}Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Tb4b4b4(Te6edf3fTb4b4b4.Te6edf3id Tff7b72in Te6edf3draftTb4b4b4)Tb4b4b4) Tff7b72return Tff7b72falseTb4b4b4;
Tff7b72return Tff7b72!Tff7b72!Te6edf3validateValueTb4b4b4(Te6edf3fTb4b4b4, Te6edf3getEffectiveValueTb4b4b4(Te6edf3nsIdTb4b4b4, Te6edf3fTb4b4b4, Te6edf3cTb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4;
Tb4b4b4}

Tff7b72function Te6edf3buildNamespacePanelTb4b4b4(Te6edf3nsIdTb4b4b4)Tb4b4b4{
T8b949e// Renders a root namespace AND any descendant namespaces as nested
T8b949e// sub-sections inside the same panel. One toolbar at the top operates on
T8b949e// the whole tree (Save / Revert / Refresh). Field rows from every namespace
T8b949e// in the tree feed into the same hasDraftError / Save-enable computation.
Tff7b72const Te6edf3wrap Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3schema Tff7b72= Te6edf3stateTb4b4b4.Te6edf3schemaTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3rootNs Tff7b72= Te6edf3schema Tff7b72&& Te6edf3getNsByIdTb4b4b4(Te6edf3schemaTb4b4b4, Te6edf3nsIdTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3rootNsTb4b4b4) Tb4b4b4{ Te6edf3wrapTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'em'Tb4b4b4, Tff7b72nullTb4b4b4, Ta5d6ff'Unknown namespace'Tb4b4b4)Tb4b4b4)Tb4b4b4; Tff7b72return Tb4b4b4{ Te6edf3nodeTff7b72: Te6edf3wrapTb4b4b4, Te6edf3cleanupsTff7b72: Tb4b4b4[Tb4b4b4] Tb4b4b4}Tb4b4b4; Tb4b4b4}
Tff7b72const Te6edf3treeIds Tff7b72= Te6edf3getNsTreeIdsTb4b4b4(Te6edf3schemaTb4b4b4, Te6edf3nsIdTb4b4b4)Tb4b4b4;

T8b949e// Header + toolbar
Tff7b72const Te6edf3header Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'h2'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'ns-h' Tb4b4b4}Tb4b4b4, Te6edf3rootNsTb4b4b4.Te6edf3nameTb4b4b4)Tb4b4b4;
Te6edf3wrapTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3headerTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3toolbar Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'ns-toolbar' Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3saveBtn Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'button'Tb4b4b4, Tff7b72nullTb4b4b4, Ta5d6ff'Save namespace'Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3revertBtn Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'button'Tb4b4b4, Tff7b72nullTb4b4b4, Ta5d6ff'Revert'Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3refreshBtn Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'button'Tb4b4b4, Tff7b72nullTb4b4b4, Ta5d6ff'Refresh'Tb4b4b4)Tb4b4b4;
Te6edf3saveBtnTb4b4b4.Te6edf3onclick Tff7b72= Tb4b4b4(Tb4b4b4) Tb4b4b4=> Te6edf3saveNamespaceTb4b4b4(Te6edf3nsIdTb4b4b4)Tb4b4b4;
Te6edf3revertBtnTb4b4b4.Te6edf3onclick Tff7b72= Tb4b4b4(Tb4b4b4) Tb4b4b4=> Te6edf3revertNamespaceTb4b4b4(Te6edf3nsIdTb4b4b4)Tb4b4b4;
Te6edf3refreshBtnTb4b4b4.Te6edf3onclick Tff7b72= Tb4b4b4(Tb4b4b4) Tb4b4b4=> Te6edf3refreshNamespaceTb4b4b4(Te6edf3nsIdTb4b4b4)Tb4b4b4;
Te6edf3toolbarTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3saveBtnTb4b4b4)Tb4b4b4;
Te6edf3toolbarTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3revertBtnTb4b4b4)Tb4b4b4;
Te6edf3toolbarTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3refreshBtnTb4b4b4)Tb4b4b4;
Te6edf3wrapTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3toolbarTb4b4b4)Tb4b4b4;

T8b949e// Build one section per namespace in the tree. The root namespace's fields
T8b949e// come first, then each descendant in depth-first order. Each descendant
T8b949e// gets a sub-section heading (h3) so the user sees the hierarchy.
Tff7b72const Te6edf3fieldHandles Tff7b72= Tb4b4b4[Tb4b4b4]Tb4b4b4;
T8b949e// Depth of a namespace relative to the panel's root. Depth 0 = the root
T8b949e// itself (rendered as the h2 at the top), depth 1 = direct child rendered as
T8b949e// "section" (h3), depth 2 = grandchild rendered as "sub-section" (h4), and
T8b949e// depth 3+ keeps stepping down to h5 with progressive indentation.
Tff7b72function Te6edf3depthOfTb4b4b4(Te6edf3idTb4b4b4)Tb4b4b4{
Tff7b72if Tb4b4b4(Tffa657NumberTb4b4b4(Te6edf3idTb4b4b4) Tff7b72=== Tffa657NumberTb4b4b4(Te6edf3nsIdTb4b4b4)Tb4b4b4) Tff7b72return T79c0ff0Tb4b4b4;
Tff7b72let Te6edf3cur Tff7b72= Te6edf3getNsByIdTb4b4b4(Te6edf3schemaTb4b4b4, Te6edf3idTb4b4b4)Tb4b4b4;
Tff7b72let Te6edf3d Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72while Tb4b4b4(Te6edf3cur Tff7b72&& Tffa657NumberTb4b4b4(Te6edf3curTb4b4b4.Te6edf3idTb4b4b4) Tff7b72!== Tffa657NumberTb4b4b4(Te6edf3nsIdTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3dTff7b72++Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3curTb4b4b4.Te6edf3parentIdTb4b4b4) Tff7b72return Tff7b72-T79c0ff1Tb4b4b4; T8b949e// not actually a descendant of nsId
Te6edf3cur Tff7b72= Te6edf3getNsByIdTb4b4b4(Te6edf3schemaTb4b4b4, Te6edf3curTb4b4b4.Te6edf3parentIdTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3d Tff7b72> T79c0ff32Tb4b4b4) Tff7b72breakTb4b4b4; T8b949e// cycle / pathological depth guard
Tb4b4b4}
Tff7b72return Te6edf3cur Tff7b72? Te6edf3d Tff7b72: Tff7b72-T79c0ff1Tb4b4b4;
Tb4b4b4}
T8b949e// Pixels of left-indent per depth level. Matched between heading and the
T8b949e// fields container so a sub-section's fields line up under its heading.
Tff7b72const Te6edf3INDENT_PX Tff7b72= T79c0ff16Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3id Tff7b72of Te6edf3treeIdsTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3ns Tff7b72= Te6edf3getNsByIdTb4b4b4(Te6edf3schemaTb4b4b4, Te6edf3idTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3nsTb4b4b4) Tff7b72continueTb4b4b4;
Tff7b72const Te6edf3depth Tff7b72= Te6edf3depthOfTb4b4b4(Te6edf3idTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3id Tff7b72!== Te6edf3nsIdTb4b4b4) Tb4b4b4{
T8b949e// Heading tag scales with depth so the visual hierarchy reads naturally:
T8b949e// h3 for top-level sections under the root, h4 for sub-sections,
T8b949e// h5 for deeper nesting (which is rare but supported).
Tff7b72const Te6edf3tag Tff7b72= Te6edf3depth Tff7b72=== T79c0ff1 Tff7b72? Ta5d6ff'h3' Tff7b72: Tb4b4b4(Te6edf3depth Tff7b72=== T79c0ff2 Tff7b72? Ta5d6ff'h4' Tff7b72: Ta5d6ff'h5'Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3cls Tff7b72= Ta5d6ff`Ta5d6ffns-sub depth-Tffd700${Tffa657MathTb4b4b4.Te6edf3minTb4b4b4(Te6edf3depthTb4b4b4, T79c0ff3Tb4b4b4)Tffd700}Ta5d6ff`Tb4b4b4;
Tff7b72const Te6edf3indent Tff7b72= Tb4b4b4(Te6edf3depth Tff7b72- T79c0ff1Tb4b4b4) Tff7b72* Te6edf3INDENT_PXTb4b4b4;
Te6edf3wrapTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Te6edf3tagTb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Te6edf3clsTb4b4b4, Te6edf3styleTff7b72: Tb4b4b4{ Te6edf3marginLeftTff7b72: Te6edf3indent Tff7b72+ Ta5d6ff'px' Tb4b4b4} Tb4b4b4}Tb4b4b4, Te6edf3nsTb4b4b4.Te6edf3nameTb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72const Te6edf3indent Tff7b72= Te6edf3depth Tff7b72> T79c0ff0 Tff7b72? Tb4b4b4(Tb4b4b4(Te6edf3depth Tff7b72- T79c0ff1Tb4b4b4) Tff7b72* Te6edf3INDENT_PXTb4b4b4) Tff7b72+ Ta5d6ff'px' Tff7b72: Ta5d6ff'0'Tb4b4b4;
Tff7b72const Te6edf3hasOwnFields Tff7b72= Te6edf3nsTb4b4b4.Te6edf3fields Tff7b72&& Te6edf3nsTb4b4b4.Te6edf3fieldsTb4b4b4.Te6edf3length Tff7b72> T79c0ff0Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3hasOwnFieldsTb4b4b4) Tb4b4b4{
T8b949e// Suppress the "(no fields)" placeholder when this namespace is a
T8b949e// container for child namespaces — they render in subsequent iterations
T8b949e// of this same treeIds loop.
Tff7b72const Te6edf3hasChildren Tff7b72= Te6edf3getChildrenOfTb4b4b4(Te6edf3schemaTb4b4b4, Te6edf3idTb4b4b4)Tb4b4b4.Te6edf3length Tff7b72> T79c0ff0Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3hasChildrenTb4b4b4) Tb4b4b4{
Te6edf3wrapTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'ns-empty'Tb4b4b4,
Te6edf3styleTff7b72: Tb4b4b4{ Te6edf3colorTff7b72: Ta5d6ff'var(--muted)'Tb4b4b4, Te6edf3fontStyleTff7b72: Ta5d6ff'italic'Tb4b4b4, Te6edf3marginLeftTff7b72: Te6edf3indent Tb4b4b4} Tb4b4b4}Tb4b4b4,
Ta5d6ff'(no fields)'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72continueTb4b4b4;
Tb4b4b4}
Tff7b72const Te6edf3section Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'ns-sub-fields'Tb4b4b4, Te6edf3styleTff7b72: Tb4b4b4{ Te6edf3marginLeftTff7b72: Te6edf3indent Tb4b4b4} Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3f Tff7b72of Te6edf3nsTb4b4b4.Te6edf3fieldsTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3h Tff7b72= Te6edf3buildFieldRowTb4b4b4(Te6edf3idTb4b4b4, Te6edf3fTb4b4b4)Tb4b4b4;
Te6edf3sectionTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3hTb4b4b4.Te6edf3rowTb4b4b4)Tb4b4b4;
Te6edf3fieldHandlesTb4b4b4.Te6edf3pushTb4b4b4(Te6edf3hTb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3wrapTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3sectionTb4b4b4)Tb4b4b4;
Tb4b4b4}

Tff7b72function Te6edf3updateButtonsTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3hasDraft Tff7b72= Te6edf3nsTreeDraftCountTb4b4b4(Te6edf3schemaTb4b4b4, Te6edf3nsIdTb4b4b4) Tff7b72> T79c0ff0Tb4b4b4;
Tff7b72const Te6edf3anyErr Tff7b72= Te6edf3fieldHandlesTb4b4b4.Te6edf3someTb4b4b4(Te6edf3h Tb4b4b4=> Te6edf3hTb4b4b4.Te6edf3hasDraftErrorTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3saveBtnTb4b4b4.Te6edf3disabled Tff7b72= Tff7b72!Te6edf3hasDraft Tff7b72|| Te6edf3anyErrTb4b4b4;
Te6edf3saveBtnTb4b4b4.Te6edf3classListTb4b4b4.Te6edf3toggleTb4b4b4(Ta5d6ff'primary'Tb4b4b4, Te6edf3hasDraft Tff7b72&& Tff7b72!Te6edf3anyErrTb4b4b4)Tb4b4b4;
Te6edf3revertBtnTb4b4b4.Te6edf3disabled Tff7b72= Tff7b72!Te6edf3hasDraftTb4b4b4;
Tb4b4b4}
Tff7b72function Te6edf3updateAllTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3h Tff7b72of Te6edf3fieldHandlesTb4b4b4) Te6edf3hTb4b4b4.Te6edf3updateTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3updateButtonsTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3updateAllTb4b4b4(Tb4b4b4)Tb4b4b4;

Tff7b72const Te6edf3cleanups Tff7b72= Tb4b4b4[
Te6edf3stateTb4b4b4.Te6edf3nsStateTb4b4b4.Te6edf3subscribeTb4b4b4(Te6edf3updateAllTb4b4b4)Tb4b4b4,
Te6edf3stateTb4b4b4.Te6edf3nsServerErrorsTb4b4b4.Te6edf3subscribeTb4b4b4(Te6edf3updateAllTb4b4b4)Tb4b4b4,
Tb4b4b4]Tb4b4b4;
Tff7b72return Tb4b4b4{ Te6edf3nodeTff7b72: Te6edf3wrapTb4b4b4, Te6edf3cleanups Tb4b4b4}Tb4b4b4;
Tb4b4b4}

Tff7b72function Te6edf3buildConfigTabTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3root Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'tab-body config-tab no-pad' Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3sidenav Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'sidenav' Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3detail Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'sidenav-detail' Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3rootTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3sidenavTb4b4b4)Tb4b4b4;
Te6edf3rootTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3detailTb4b4b4)Tb4b4b4;

T8b949e// Cleanup for the inner-mounted namespace panel
Tff7b72let Te6edf3nsCleanups Tff7b72= Tb4b4b4[Tb4b4b4]Tb4b4b4;
T8b949e// After this many ms in the "Loading…" state, show a "timed out + Refresh"
T8b949e// view. Matches the RNS request timeout so on a stalled connection the
T8b949e// UI surfaces a retry control instead of an indefinite spinner.
Tff7b72const Te6edf3LOAD_TIMEOUT_MS Tff7b72= T79c0ff30000Tb4b4b4;
Tff7b72function Te6edf3mountNsTb4b4b4(Te6edf3nsIdTb4b4b4)Tb4b4b4{
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3fn Tff7b72of Te6edf3nsCleanupsTb4b4b4) Tb4b4b4{ Tff7b72try Tb4b4b4{ Te6edf3fnTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4} Tb4b4b4}
Te6edf3nsCleanups Tff7b72= Tb4b4b4[Tb4b4b4]Tb4b4b4;
Te6edf3detailTb4b4b4.Te6edf3innerHTML Tff7b72= Ta5d6ff''Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3nsId Tff7b72== Tff7b72nullTb4b4b4) Tb4b4b4{ Te6edf3detailTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'em'Tb4b4b4, Tff7b72nullTb4b4b4, Ta5d6ff'Select a namespace from the left.'Tb4b4b4)Tb4b4b4)Tb4b4b4; Tff7b72returnTb4b4b4; Tb4b4b4}
T8b949e// Treat the panel as "loaded" only when EVERY namespace in the tree has
T8b949e// been fetched — otherwise show "Loading…" so partial sub-sections don't
T8b949e// render with empty default values.
Tff7b72const Te6edf3schema Tff7b72= Te6edf3stateTb4b4b4.Te6edf3schemaTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3treeIds Tff7b72= Te6edf3schema Tff7b72? Te6edf3getNsTreeIdsTb4b4b4(Te6edf3schemaTb4b4b4, Te6edf3nsIdTb4b4b4) Tff7b72: Tb4b4b4[Tffa657NumberTb4b4b4(Te6edf3nsIdTb4b4b4)Tb4b4b4]Tb4b4b4;
Tff7b72const Te6edf3loaded Tff7b72= Te6edf3stateTb4b4b4.Te6edf3nsLoadedTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3allLoaded Tff7b72= Te6edf3treeIdsTb4b4b4.Te6edf3length Tff7b72> T79c0ff0 Tff7b72&& Te6edf3treeIdsTb4b4b4.Te6edf3everyTb4b4b4(Te6edf3id Tb4b4b4=> Tff7b72!Tff7b72!Te6edf3loadedTb4b4b4[Te6edf3idTb4b4b4]Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3allLoadedTb4b4b4) Tb4b4b4{
Te6edf3detailTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'em'Tb4b4b4, Tff7b72nullTb4b4b4, Ta5d6ff'Loading…'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3timerId Tff7b72= Te6edf3setTimeoutTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
T8b949e// Only swap to the timeout view if we're still in the loading state —
T8b949e// a successful fetch in the meantime will have re-entered mountNs and
T8b949e// cleared this timer via nsCleanups.
Tff7b72const Te6edf3cur Tff7b72= Te6edf3stateTb4b4b4.Te6edf3nsLoadedTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3stillLoading Tff7b72= Tff7b72!Tb4b4b4(Te6edf3treeIdsTb4b4b4.Te6edf3length Tff7b72> T79c0ff0 Tff7b72&& Te6edf3treeIdsTb4b4b4.Te6edf3everyTb4b4b4(Te6edf3id Tb4b4b4=> Tff7b72!Tff7b72!Te6edf3curTb4b4b4[Te6edf3idTb4b4b4]Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3stillLoadingTb4b4b4) Tff7b72returnTb4b4b4;
Te6edf3detailTb4b4b4.Te6edf3innerHTML Tff7b72= Ta5d6ff''Tb4b4b4;
Te6edf3detailTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'notice' Tb4b4b4}Tb4b4b4, Ta5d6ff'Loading timed out.'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3retry Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'button'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'primary'Tb4b4b4, Te6edf3onclickTff7b72: Tb4b4b4(Tb4b4b4) Tb4b4b4=> Te6edf3refreshNamespaceTb4b4b4(Te6edf3nsIdTb4b4b4) Tb4b4b4}Tb4b4b4, Ta5d6ff'Refresh'Tb4b4b4)Tb4b4b4;
Te6edf3detailTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3retryTb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4, Te6edf3LOAD_TIMEOUT_MSTb4b4b4)Tb4b4b4;
Te6edf3nsCleanupsTb4b4b4.Te6edf3pushTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Te6edf3clearTimeoutTb4b4b4(Te6edf3timerIdTb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3fetchNamespaceIfNeededTb4b4b4(Te6edf3nsIdTb4b4b4)Tb4b4b4;
Tff7b72returnTb4b4b4;
Tb4b4b4}
Tff7b72const Tb4b4b4{ Te6edf3nodeTb4b4b4, Te6edf3cleanups Tb4b4b4} Tff7b72= Te6edf3buildNamespacePanelTb4b4b4(Te6edf3nsIdTb4b4b4)Tb4b4b4;
Te6edf3nsCleanups Tff7b72= Te6edf3cleanupsTb4b4b4;
Te6edf3detailTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3nodeTb4b4b4)Tb4b4b4;
Tb4b4b4}

Tff7b72const Te6edf3navButtons Tff7b72= Tff7b72new Tffa657MapTb4b4b4(Tb4b4b4)Tb4b4b4; T8b949e// rootNsId -> { btn, dot }
Tff7b72function Te6edf3rebuildSidenavTb4b4b4(Tb4b4b4)Tb4b4b4{
Te6edf3sidenavTb4b4b4.Te6edf3innerHTML Tff7b72= Ta5d6ff''Tb4b4b4;
Te6edf3navButtonsTb4b4b4.Te6edf3clearTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3schema Tff7b72= Te6edf3stateTb4b4b4.Te6edf3schemaTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3schemaTb4b4b4) Tb4b4b4{ Te6edf3sidenavTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'em'Tb4b4b4, Tb4b4b4{ Te6edf3styleTff7b72: Tb4b4b4{ Te6edf3paddingTff7b72: Ta5d6ff'8px 16px'Tb4b4b4, Te6edf3colorTff7b72: Ta5d6ff'var(--muted)' Tb4b4b4} Tb4b4b4}Tb4b4b4, Ta5d6ff'No schema'Tb4b4b4)Tb4b4b4)Tb4b4b4; Tff7b72returnTb4b4b4; Tb4b4b4}
T8b949e// Only root namespaces (parentId == 0) get top-level sidenav entries.
T8b949e// Children render as sub-sections inside their root's panel.
Tff7b72const Te6edf3roots Tff7b72= Te6edf3schemaTb4b4b4.Te6edf3namespacesTb4b4b4.Te6edf3filterTb4b4b4(Te6edf3n Tb4b4b4=> Tff7b72!Tffa657NumberTb4b4b4(Te6edf3nTb4b4b4.Te6edf3parentId Tff7b72|| T79c0ff0Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3activeNs Tff7b72= Te6edf3stateTb4b4b4.Te6edf3activeNsTabTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3ns Tff7b72of Te6edf3rootsTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3b Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'button'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'sidenav-btn' Tff7b72+ Tb4b4b4(Te6edf3nsTb4b4b4.Te6edf3id Tff7b72=== Te6edf3activeNs Tff7b72? Ta5d6ff' active' Tff7b72: Ta5d6ff''Tb4b4b4)Tb4b4b4, Te6edf3onclickTff7b72: Tb4b4b4(Tb4b4b4) Tb4b4b4=> Te6edf3stateTb4b4b4.Te6edf3activeNsTabTb4b4b4.Te6edf3setTb4b4b4(Te6edf3nsTb4b4b4.Te6edf3idTb4b4b4) Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3lbl Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'span'Tb4b4b4, Tff7b72nullTb4b4b4, Te6edf3nsTb4b4b4.Te6edf3nameTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3dot Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'span'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'dot'Tb4b4b4, Te6edf3styleTff7b72: Tb4b4b4{ Te6edf3displayTff7b72: Te6edf3nsTreeDraftCountTb4b4b4(Te6edf3schemaTb4b4b4, Te6edf3nsTb4b4b4.Te6edf3idTb4b4b4) Tff7b72> T79c0ff0 Tff7b72? Ta5d6ff'' Tff7b72: Ta5d6ff'none' Tb4b4b4} Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3bTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3lblTb4b4b4)Tb4b4b4;
Te6edf3bTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3dotTb4b4b4)Tb4b4b4;
Te6edf3sidenavTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3bTb4b4b4)Tb4b4b4;
Te6edf3navButtonsTb4b4b4.Te6edf3setTb4b4b4(Te6edf3nsTb4b4b4.Te6edf3idTb4b4b4, Tb4b4b4{ Te6edf3btnTff7b72: Te6edf3bTb4b4b4, Te6edf3dot Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72function Te6edf3updateNavActiveTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3active Tff7b72= Te6edf3stateTb4b4b4.Te6edf3activeNsTabTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72const Tb4b4b4[Te6edf3nsIdTb4b4b4, Tb4b4b4{ Te6edf3btn Tb4b4b4}Tb4b4b4] Tff7b72of Te6edf3navButtonsTb4b4b4) Tb4b4b4{
Te6edf3btnTb4b4b4.Te6edf3classListTb4b4b4.Te6edf3toggleTb4b4b4(Ta5d6ff'active'Tb4b4b4, Te6edf3nsId Tff7b72=== Te6edf3activeTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72function Te6edf3updateNavDotsTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3schema Tff7b72= Te6edf3stateTb4b4b4.Te6edf3schemaTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72const Tb4b4b4[Te6edf3nsIdTb4b4b4, Tb4b4b4{ Te6edf3dot Tb4b4b4}Tb4b4b4] Tff7b72of Te6edf3navButtonsTb4b4b4) Tb4b4b4{
Te6edf3dotTb4b4b4.Te6edf3styleTb4b4b4.Te6edf3display Tff7b72= Te6edf3nsTreeDraftCountTb4b4b4(Te6edf3schemaTb4b4b4, Te6edf3nsIdTb4b4b4) Tff7b72> T79c0ff0 Tff7b72? Ta5d6ff'' Tff7b72: Ta5d6ff'none'Tb4b4b4;
Tb4b4b4}
Tb4b4b4}

T8b949e// Pick a root namespace as the default selection (skip non-root children).
Te6edf3rebuildSidenavTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3sch Tff7b72= Te6edf3stateTb4b4b4.Te6edf3schemaTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sch Tff7b72&& Te6edf3stateTb4b4b4.Te6edf3activeNsTabTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4) Tff7b72== Tff7b72nullTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3firstRoot Tff7b72= Te6edf3schTb4b4b4.Te6edf3namespacesTb4b4b4.Te6edf3findTb4b4b4(Te6edf3n Tb4b4b4=> Tff7b72!Tffa657NumberTb4b4b4(Te6edf3nTb4b4b4.Te6edf3parentId Tff7b72|| T79c0ff0Tb4b4b4)Tb4b4b4) Tff7b72|| Te6edf3schTb4b4b4.Te6edf3namespacesTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3firstRootTb4b4b4) Te6edf3stateTb4b4b4.Te6edf3activeNsTabTb4b4b4.Te6edf3setTb4b4b4(Te6edf3firstRootTb4b4b4.Te6edf3idTb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3sch Tff7b72&& Te6edf3stateTb4b4b4.Te6edf3activeNsTabTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4) Tff7b72!= Tff7b72nullTb4b4b4) Tb4b4b4{
T8b949e// If the previously-selected ns is a child (e.g. saved from a v1 schema
T8b949e// session), redirect to its root so the panel renders correctly.
Tff7b72const Te6edf3cur Tff7b72= Te6edf3getNsByIdTb4b4b4(Te6edf3schTb4b4b4, Te6edf3stateTb4b4b4.Te6edf3activeNsTabTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3cur Tff7b72&& Tffa657NumberTb4b4b4(Te6edf3curTb4b4b4.Te6edf3parentId Tff7b72|| T79c0ff0Tb4b4b4) Tff7b72!== T79c0ff0Tb4b4b4) Tb4b4b4{
Tff7b72let Te6edf3root Tff7b72= Te6edf3curTb4b4b4;
Tff7b72while Tb4b4b4(Te6edf3root Tff7b72&& Te6edf3rootTb4b4b4.Te6edf3parentIdTb4b4b4) Te6edf3root Tff7b72= Te6edf3getNsByIdTb4b4b4(Te6edf3schTb4b4b4, Te6edf3rootTb4b4b4.Te6edf3parentIdTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3rootTb4b4b4) Te6edf3stateTb4b4b4.Te6edf3activeNsTabTb4b4b4.Te6edf3setTb4b4b4(Te6edf3rootTb4b4b4.Te6edf3idTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Te6edf3mountNsTb4b4b4(Te6edf3stateTb4b4b4.Te6edf3activeNsTabTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;

Te6edf3bodyCleanupsTb4b4b4.Te6edf3pushTb4b4b4(Te6edf3stateTb4b4b4.Te6edf3schemaTb4b4b4.Te6edf3subscribeTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{ Te6edf3rebuildSidenavTb4b4b4(Tb4b4b4)Tb4b4b4; Te6edf3mountNsTb4b4b4(Te6edf3stateTb4b4b4.Te6edf3activeNsTabTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4; Tb4b4b4}Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3bodyCleanupsTb4b4b4.Te6edf3pushTb4b4b4(Te6edf3stateTb4b4b4.Te6edf3activeNsTabTb4b4b4.Te6edf3subscribeTb4b4b4(Tb4b4b4(Te6edf3nsIdTb4b4b4) Tb4b4b4=> Tb4b4b4{ Te6edf3updateNavActiveTb4b4b4(Tb4b4b4)Tb4b4b4; Te6edf3mountNsTb4b4b4(Te6edf3nsIdTb4b4b4)Tb4b4b4; Tb4b4b4}Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3bodyCleanupsTb4b4b4.Te6edf3pushTb4b4b4(Te6edf3stateTb4b4b4.Te6edf3nsLoadedTb4b4b4.Te6edf3subscribeTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
T8b949e// Remount on every nsLoaded change so transitions in both directions are
T8b949e// visible: loaded → invalidated (Refresh / Save / Commit) shows the
T8b949e// "Loading…" placeholder again with a fresh 30s timeout, and
T8b949e// invalidated → loaded swaps back to the populated panel.
Tff7b72const Te6edf3cur Tff7b72= Te6edf3stateTb4b4b4.Te6edf3activeNsTabTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3cur Tff7b72!= Tff7b72nullTb4b4b4) Te6edf3mountNsTb4b4b4(Te6edf3curTb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3bodyCleanupsTb4b4b4.Te6edf3pushTb4b4b4(Te6edf3stateTb4b4b4.Te6edf3nsStateTb4b4b4.Te6edf3subscribeTb4b4b4(Te6edf3updateNavDotsTb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3bodyCleanupsTb4b4b4.Te6edf3pushTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{ Tff7b72for Tb4b4b4(Tff7b72const Te6edf3fn Tff7b72of Te6edf3nsCleanupsTb4b4b4) Tff7b72try Tb4b4b4{ Te6edf3fnTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4} Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72return Te6edf3rootTb4b4b4;
Tb4b4b4}

T8b949e// ===== Node Config tab =====
T8b949e// Master/detail with a statically-defined sidenav (sections from
T8b949e// NODE_CONFIG_SCHEMA). Each section is either standard schema-driven (Radio,
T8b949e// WiFi, Display) or custom (Device Info, Mode, Bluetooth, EEPROM).

Tff7b72function Te6edf3ncfgDraftCountTb4b4b4(Te6edf3sectionIdTb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3s Tff7b72= Te6edf3stateTb4b4b4.Te6edf3nodeCfgStateTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4[Te6edf3sectionIdTb4b4b4]Tb4b4b4;
Tff7b72return Te6edf3s Tff7b72? Tffa657ObjectTb4b4b4.Te6edf3keysTb4b4b4(Te6edf3sTb4b4b4.Te6edf3draft Tff7b72|| Tb4b4b4{Tb4b4b4}Tb4b4b4)Tb4b4b4.Te6edf3length Tff7b72: T79c0ff0Tb4b4b4;
Tb4b4b4}

Tff7b72async Tff7b72function Te6edf3ncfgFetchSectionTb4b4b4(Te6edf3sectionIdTb4b4b4)Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3legacyTb4b4b4) Tff7b72returnTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3stateTb4b4b4.Te6edf3nodeCfgLoadedTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4[Te6edf3sectionIdTb4b4b4] Tff7b72|| Te6edf3stateTb4b4b4.Te6edf3nodeCfgLoadingTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4[Te6edf3sectionIdTb4b4b4]Tb4b4b4) Tff7b72returnTb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nodeCfgLoadingTb4b4b4.Te6edf3updateTb4b4b4(Te6edf3s Tb4b4b4=> Tb4b4b4{ Te6edf3sTb4b4b4[Te6edf3sectionIdTb4b4b4] Tff7b72= Tff7b72trueTb4b4b4; Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72try Tb4b4b4{
Tff7b72const Te6edf3sec Tff7b72= Te6edf3NODE_CONFIG_SCHEMATb4b4b4[Te6edf3sectionIdTb4b4b4]Tb4b4b4;
T8b949e// Section may declare a custom `readFn` for cases where the per-field
T8b949e// legacy queries aren't enough (e.g. WiFi config, whose CMD_WIFI_*
T8b949e// opcodes are write-only — the values live in EEPROM and have to be
T8b949e// read back via CMD_ROM_READ / CMD_CFG_READ and decoded).
Tff7b72const Te6edf3committed Tff7b72= Te6edf3sec Tff7b72&& Tff7b72typeof Te6edf3secTb4b4b4.Te6edf3readFn Tff7b72=== Ta5d6ff'function'
Tff7b72? Tff7b72await Te6edf3secTb4b4b4.Te6edf3readFnTb4b4b4(Te6edf3legacyTb4b4b4)
Tff7b72: Tff7b72await Te6edf3legacyTb4b4b4.Te6edf3readSectionTb4b4b4(Te6edf3sectionIdTb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nodeCfgStateTb4b4b4.Te6edf3updateTb4b4b4(Te6edf3s Tb4b4b4=> Tb4b4b4{ Te6edf3sTb4b4b4[Te6edf3sectionIdTb4b4b4] Tff7b72= Tb4b4b4{ Te6edf3committedTb4b4b4, Te6edf3draftTff7b72: Tb4b4b4{Tb4b4b4} Tb4b4b4}Tb4b4b4; Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nodeCfgLoadedTb4b4b4.Te6edf3updateTb4b4b4(Te6edf3s Tb4b4b4=> Tb4b4b4{ Te6edf3sTb4b4b4[Te6edf3sectionIdTb4b4b4] Tff7b72= Tff7b72trueTb4b4b4; Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{
Te6edf3consoleTb4b4b4.Te6edf3errorTb4b4b4(Ta5d6ff'Node Config read failed:'Tb4b4b4, Te6edf3eTb4b4b4)Tb4b4b4;
Te6edf3showToastTb4b4b4(Ta5d6ff'Failed to read ' Tff7b72+ Te6edf3sectionId Tff7b72+ Ta5d6ff': ' Tff7b72+ Te6edf3eTb4b4b4.Te6edf3messageTb4b4b4, Ta5d6ff'err'Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72finally Tb4b4b4{
Te6edf3stateTb4b4b4.Te6edf3nodeCfgLoadingTb4b4b4.Te6edf3updateTb4b4b4(Te6edf3s Tb4b4b4=> Tb4b4b4{ Tff7b72delete Te6edf3sTb4b4b4[Te6edf3sectionIdTb4b4b4]Tb4b4b4; Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}

Tff7b72async Tff7b72function Te6edf3ncfgSaveSectionTb4b4b4(Te6edf3sectionIdTb4b4b4)Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3legacyTb4b4b4) Tff7b72returnTb4b4b4;
Tff7b72const Te6edf3sec Tff7b72= Te6edf3NODE_CONFIG_SCHEMATb4b4b4[Te6edf3sectionIdTb4b4b4]Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3secTb4b4b4) Tff7b72returnTb4b4b4;
Tff7b72const Te6edf3obj Tff7b72= Te6edf3stateTb4b4b4.Te6edf3nodeCfgStateTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4[Te6edf3sectionIdTb4b4b4]Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3obj Tff7b72|| Tffa657ObjectTb4b4b4.Te6edf3keysTb4b4b4(Te6edf3objTb4b4b4.Te6edf3draftTb4b4b4)Tb4b4b4.Te6edf3length Tff7b72=== T79c0ff0Tb4b4b4) Tff7b72returnTb4b4b4;
Tff7b72try Tb4b4b4{
Tff7b72await Te6edf3legacyTb4b4b4.Te6edf3writeSectionTb4b4b4(Te6edf3sectionIdTb4b4b4, Te6edf3objTb4b4b4.Te6edf3draftTb4b4b4)Tb4b4b4;
T8b949e// Treat the draft as the new committed state. (We don't re-read because many
T8b949e// legacy CMDs are write-only — no read counterpart on the firmware side.)
Te6edf3stateTb4b4b4.Te6edf3nodeCfgStateTb4b4b4.Te6edf3updateTb4b4b4(Te6edf3s Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3committed Tff7b72= Tb4b4b4{ Tb4b4b4...Te6edf3objTb4b4b4.Te6edf3committedTb4b4b4, Tb4b4b4...Te6edf3objTb4b4b4.Te6edf3draft Tb4b4b4}Tb4b4b4;
Te6edf3sTb4b4b4[Te6edf3sectionIdTb4b4b4] Tff7b72= Tb4b4b4{ Te6edf3committedTb4b4b4, Te6edf3draftTff7b72: Tb4b4b4{Tb4b4b4} Tb4b4b4}Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3recomputeHasDraftTb4b4b4(Te6edf3NCFG_CTXTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3label Tff7b72= Te6edf3secTb4b4b4.Te6edf3label Tff7b72|| Te6edf3sectionIdTb4b4b4;
Te6edf3showToastTb4b4b4(Ta5d6ff`Ta5d6ffSaved Tffd700${Te6edf3labelTffd700}Ta5d6ff settingsTa5d6ff`Tb4b4b4, Ta5d6ff'ok'Tb4b4b4)Tb4b4b4;
T8b949e// If any saveTrailer op was CMD_CONF_SAVE, the radio config was persisted —
T8b949e// remind the user that the next boot enters TNC mode.
Tff7b72const Te6edf3trailerOps Tff7b72= Te6edf3secTb4b4b4.Te6edf3saveTrailer
Tff7b72? Tb4b4b4(Tffa657ArrayTb4b4b4.Te6edf3isArrayTb4b4b4(Te6edf3secTb4b4b4.Te6edf3saveTrailerTb4b4b4) Tff7b72? Te6edf3secTb4b4b4.Te6edf3saveTrailer Tff7b72: Tb4b4b4[Te6edf3secTb4b4b4.Te6edf3saveTrailerTb4b4b4]Tb4b4b4)
Tff7b72: Tb4b4b4[Tb4b4b4]Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3trailerOpsTb4b4b4.Te6edf3someTb4b4b4(Te6edf3op Tb4b4b4=> Te6edf3opTb4b4b4.Te6edf3cmd Tff7b72=== Te6edf3CMD_CONF_SAVETb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3showToastTb4b4b4(Ta5d6ff'Radio config persisted to EEPROM (device will boot in TNC mode)'Tb4b4b4, Ta5d6ff'warn'Tb4b4b4)Tb4b4b4;
Tb4b4b4}
T8b949e// Hint the user to reboot when the saved section's changes take effect at
T8b949e// boot time (radio, wifi). Reflected in the Node Status reboot banner.
Tff7b72if Tb4b4b4(Te6edf3secTb4b4b4.Te6edf3requiresRebootTb4b4b4) Te6edf3stateTb4b4b4.Te6edf3nodeCfgNeedsRebootTb4b4b4.Te6edf3setTb4b4b4(Tff7b72trueTb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{
Te6edf3showToastTb4b4b4(Ta5d6ff'Save failed: ' Tff7b72+ Te6edf3eTb4b4b4.Te6edf3messageTb4b4b4, Ta5d6ff'err'Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}

Tff7b72function Te6edf3ncfgRevertSectionTb4b4b4(Te6edf3sectionIdTb4b4b4)Tb4b4b4{
Te6edf3stateTb4b4b4.Te6edf3nodeCfgStateTb4b4b4.Te6edf3updateTb4b4b4(Te6edf3s Tb4b4b4=> Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sTb4b4b4[Te6edf3sectionIdTb4b4b4]Tb4b4b4) Te6edf3sTb4b4b4[Te6edf3sectionIdTb4b4b4]Tb4b4b4.Te6edf3draft Tff7b72= Tb4b4b4{Tb4b4b4}Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3recomputeHasDraftTb4b4b4(Te6edf3NCFG_CTXTb4b4b4)Tb4b4b4;
Tb4b4b4}

Tff7b72function Te6edf3buildNcfgSchemaPanelTb4b4b4(Te6edf3sectionIdTb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3sec Tff7b72= Te6edf3NODE_CONFIG_SCHEMATb4b4b4[Te6edf3sectionIdTb4b4b4]Tb4b4b4;
Tff7b72const Te6edf3wrap Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'ncfg-section' Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3wrapTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'h2'Tb4b4b4, Tff7b72nullTb4b4b4, Te6edf3secTb4b4b4.Te6edf3labelTb4b4b4)Tb4b4b4)Tb4b4b4;

T8b949e// A section is fully "set-only" when every field is declared readable:false
T8b949e// and there's no readFn to surface a value some other way. Refresh is
T8b949e// meaningless in that case, and the displayed values are placeholders.
Tff7b72const Te6edf3setOnlySection Tff7b72= Tffa657ArrayTb4b4b4.Te6edf3isArrayTb4b4b4(Te6edf3secTb4b4b4.Te6edf3fieldsTb4b4b4) Tff7b72&& Te6edf3secTb4b4b4.Te6edf3fieldsTb4b4b4.Te6edf3length Tff7b72> T79c0ff0
Tff7b72&& Tff7b72typeof Te6edf3secTb4b4b4.Te6edf3readFn Tff7b72!== Ta5d6ff'function'
Tff7b72&& Te6edf3secTb4b4b4.Te6edf3fieldsTb4b4b4.Te6edf3everyTb4b4b4(Te6edf3f Tb4b4b4=> Te6edf3fTb4b4b4.Te6edf3readable Tff7b72=== Tff7b72falseTb4b4b4)Tb4b4b4;

Tff7b72const Te6edf3toolbar Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'ns-toolbar' Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3saveBtn Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'button'Tb4b4b4, Tff7b72nullTb4b4b4, Ta5d6ff'Save ' Tff7b72+ Te6edf3secTb4b4b4.Te6edf3labelTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3revertBtn Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'button'Tb4b4b4, Tff7b72nullTb4b4b4, Ta5d6ff'Revert'Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3refreshBtn Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'button'Tb4b4b4, Tff7b72nullTb4b4b4, Ta5d6ff'Refresh'Tb4b4b4)Tb4b4b4;
Te6edf3saveBtnTb4b4b4.Te6edf3onclick Tff7b72= Tb4b4b4(Tb4b4b4) Tb4b4b4=> Te6edf3ncfgSaveSectionTb4b4b4(Te6edf3sectionIdTb4b4b4)Tb4b4b4;
Te6edf3revertBtnTb4b4b4.Te6edf3onclick Tff7b72= Tb4b4b4(Tb4b4b4) Tb4b4b4=> Te6edf3ncfgRevertSectionTb4b4b4(Te6edf3sectionIdTb4b4b4)Tb4b4b4;
Te6edf3refreshBtnTb4b4b4.Te6edf3onclick Tff7b72= Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Te6edf3stateTb4b4b4.Te6edf3nodeCfgLoadedTb4b4b4.Te6edf3updateTb4b4b4(Te6edf3s Tb4b4b4=> Tb4b4b4{ Tff7b72delete Te6edf3sTb4b4b4[Te6edf3sectionIdTb4b4b4]Tb4b4b4; Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3ncfgFetchSectionTb4b4b4(Te6edf3sectionIdTb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4;
Te6edf3toolbarTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3saveBtnTb4b4b4)Tb4b4b4;
T8b949e// Revert and Refresh are meaningless for fully set-only sections (nothing
T8b949e// on the device to revert against or refresh from), so hide them entirely.
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3setOnlySectionTb4b4b4) Tb4b4b4{
Te6edf3toolbarTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3revertBtnTb4b4b4)Tb4b4b4;
Te6edf3toolbarTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3refreshBtnTb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3wrapTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3toolbarTb4b4b4)Tb4b4b4;

Tff7b72if Tb4b4b4(Te6edf3setOnlySectionTb4b4b4) Tb4b4b4{
Te6edf3wrapTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'set-only-banner' Tb4b4b4}Tb4b4b4,
Ta5d6ff'This section is write-only. The device firmware does not expose these fields for readback over KISS, so the values shown below are schema placeholders, not the current device state. Edits take effect when you click Save.'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}

Tff7b72if Tb4b4b4(Te6edf3secTb4b4b4.Te6edf3saveTrailerNoteTb4b4b4) Tb4b4b4{
Te6edf3wrapTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'ncfg-trailer' Tb4b4b4}Tb4b4b4, Te6edf3secTb4b4b4.Te6edf3saveTrailerNoteTb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}

Tff7b72const Te6edf3fieldHandles Tff7b72= Tb4b4b4[Tb4b4b4]Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3f Tff7b72of Te6edf3secTb4b4b4.Te6edf3fieldsTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3h Tff7b72= Te6edf3buildFieldRowTb4b4b4(Te6edf3sectionIdTb4b4b4, Te6edf3fTb4b4b4, Te6edf3NCFG_CTXTb4b4b4)Tb4b4b4;
Te6edf3wrapTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3hTb4b4b4.Te6edf3rowTb4b4b4)Tb4b4b4;
Te6edf3fieldHandlesTb4b4b4.Te6edf3pushTb4b4b4(Te6edf3hTb4b4b4)Tb4b4b4;
Tb4b4b4}

Tff7b72function Te6edf3updateButtonsTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3hasDraft Tff7b72= Te6edf3ncfgDraftCountTb4b4b4(Te6edf3sectionIdTb4b4b4) Tff7b72> T79c0ff0Tb4b4b4;
Tff7b72const Te6edf3anyErr Tff7b72= Te6edf3fieldHandlesTb4b4b4.Te6edf3someTb4b4b4(Te6edf3h Tb4b4b4=> Te6edf3hTb4b4b4.Te6edf3hasDraftErrorTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3saveBtnTb4b4b4.Te6edf3disabled Tff7b72= Tff7b72!Te6edf3hasDraft Tff7b72|| Te6edf3anyErrTb4b4b4;
Te6edf3saveBtnTb4b4b4.Te6edf3classListTb4b4b4.Te6edf3toggleTb4b4b4(Ta5d6ff'primary'Tb4b4b4, Te6edf3hasDraft Tff7b72&& Tff7b72!Te6edf3anyErrTb4b4b4)Tb4b4b4;
Te6edf3revertBtnTb4b4b4.Te6edf3disabled Tff7b72= Tff7b72!Te6edf3hasDraftTb4b4b4;
Tb4b4b4}
Tff7b72function Te6edf3updateAllTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3h Tff7b72of Te6edf3fieldHandlesTb4b4b4) Te6edf3hTb4b4b4.Te6edf3updateTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3updateButtonsTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3updateAllTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3cleanups Tff7b72= Tb4b4b4[
Te6edf3stateTb4b4b4.Te6edf3nodeCfgStateTb4b4b4.Te6edf3subscribeTb4b4b4(Te6edf3updateAllTb4b4b4)Tb4b4b4,
Tb4b4b4]Tb4b4b4;
Tff7b72return Tb4b4b4{ Te6edf3nodeTff7b72: Te6edf3wrapTb4b4b4, Te6edf3cleanups Tb4b4b4}Tb4b4b4;
Tb4b4b4}

Tff7b72function Te6edf3buildNcfgDeviceInfoPanelTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3wrap Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'ncfg-section' Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3wrapTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'h2'Tb4b4b4, Tff7b72nullTb4b4b4, Ta5d6ff'Device Info'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3refreshBtn Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'button'Tb4b4b4, Tff7b72nullTb4b4b4, Ta5d6ff'Refresh'Tb4b4b4)Tb4b4b4;
Te6edf3refreshBtnTb4b4b4.Te6edf3onclick Tff7b72= Tff7b72async Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3legacyTb4b4b4) Tff7b72returnTb4b4b4;
Te6edf3refreshBtnTb4b4b4.Te6edf3disabled Tff7b72= Tff7b72trueTb4b4b4;
Te6edf3refreshBtnTb4b4b4.Te6edf3textContent Tff7b72= Ta5d6ff'Reading…'Tb4b4b4;
Tff7b72try Tb4b4b4{
Tff7b72const Te6edf3info Tff7b72= Tff7b72await Te6edf3legacyTb4b4b4.Te6edf3readDeviceInfoTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nodeCfgDeviceInfoTb4b4b4.Te6edf3setTb4b4b4(Te6edf3infoTb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{
Te6edf3showToastTb4b4b4(Ta5d6ff'Device info read failed: ' Tff7b72+ Te6edf3eTb4b4b4.Te6edf3messageTb4b4b4, Ta5d6ff'err'Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72finally Tb4b4b4{
Te6edf3refreshBtnTb4b4b4.Te6edf3disabled Tff7b72= Tff7b72falseTb4b4b4;
Te6edf3refreshBtnTb4b4b4.Te6edf3textContent Tff7b72= Ta5d6ff'Refresh'Tb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4;
Tff7b72const Te6edf3toolbar Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'ns-toolbar' Tb4b4b4}Tb4b4b4, Tb4b4b4[Te6edf3refreshBtnTb4b4b4]Tb4b4b4)Tb4b4b4;
Te6edf3wrapTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3toolbarTb4b4b4)Tb4b4b4;

Tff7b72const Te6edf3table Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'table'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'kv-info' Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3wrapTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3tableTb4b4b4)Tb4b4b4;

Tff7b72function Te6edf3hexOfTb4b4b4(Te6edf3u8Tb4b4b4)Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3u8Tb4b4b4) Tff7b72return Ta5d6ff''Tb4b4b4;
Tff7b72return Tffa657ArrayTb4b4b4.Tff7b72fromTb4b4b4(Te6edf3u8Tb4b4b4)Tb4b4b4.Te6edf3mapTb4b4b4(Te6edf3b Tb4b4b4=> Te6edf3bTb4b4b4.Te6edf3toStringTb4b4b4(T79c0ff16Tb4b4b4)Tb4b4b4.Te6edf3padStartTb4b4b4(T79c0ff2Tb4b4b4,Ta5d6ff'0'Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3joinTb4b4b4(Ta5d6ff''Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72function Te6edf3rowTb4b4b4(Te6edf3labelTb4b4b4, Te6edf3valTb4b4b4, Te6edf3clsTb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3td Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'td'Tb4b4b4, Te6edf3cls Tff7b72? Tb4b4b4{ Tff7b72classTff7b72: Te6edf3cls Tb4b4b4} Tff7b72: Tff7b72nullTb4b4b4, Te6edf3val Tff7b72== Tff7b72null Tff7b72? Ta5d6ff'—' Tff7b72: Te6edf3valTb4b4b4)Tb4b4b4;
Tff7b72return Te6edf3elTb4b4b4(Ta5d6ff'tr'Tb4b4b4, Tff7b72nullTb4b4b4, Tb4b4b4[Te6edf3elTb4b4b4(Ta5d6ff'td'Tb4b4b4, Tff7b72nullTb4b4b4, Te6edf3labelTb4b4b4)Tb4b4b4, Te6edf3tdTb4b4b4]Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72function Te6edf3updateTb4b4b4(Tb4b4b4)Tb4b4b4{
Te6edf3tableTb4b4b4.Te6edf3innerHTML Tff7b72= Ta5d6ff''Tb4b4b4;
Tff7b72const Te6edf3info Tff7b72= Te6edf3stateTb4b4b4.Te6edf3nodeCfgDeviceInfoTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3infoTb4b4b4) Tb4b4b4{
Te6edf3tableTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'tr'Tb4b4b4, Tff7b72nullTb4b4b4, Tb4b4b4[Te6edf3elTb4b4b4(Ta5d6ff'td'Tb4b4b4, Tff7b72nullTb4b4b4, Ta5d6ff''Tb4b4b4)Tb4b4b4, Te6edf3elTb4b4b4(Ta5d6ff'td'Tb4b4b4, Tff7b72nullTb4b4b4,
Te6edf3elTb4b4b4(Ta5d6ff'em'Tb4b4b4, Tff7b72nullTb4b4b4, Ta5d6ff'Click Refresh to read device information.'Tb4b4b4)Tb4b4b4)Tb4b4b4]Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72returnTb4b4b4;
Tb4b4b4}
Tff7b72const Te6edf3boardLbl Tff7b72= Te6edf3infoTb4b4b4.Te6edf3board Tff7b72!= Tff7b72null Tff7b72? Ta5d6ff`Tffd700${Te6edf3BOARD_NAMESTb4b4b4[Te6edf3infoTb4b4b4.Te6edf3boardTb4b4b4] Tff7b72|| Ta5d6ff'Unknown'Tffd700}Ta5d6ff (0xTffd700${Te6edf3infoTb4b4b4.Te6edf3boardTb4b4b4.Te6edf3toStringTb4b4b4(T79c0ff16Tb4b4b4)Tb4b4b4.Te6edf3padStartTb4b4b4(T79c0ff2Tb4b4b4,Ta5d6ff'0'Tb4b4b4)Tffd700}Ta5d6ff)Ta5d6ff` Tff7b72: Tff7b72nullTb4b4b4;
Tff7b72const Te6edf3platLbl Tff7b72= Te6edf3infoTb4b4b4.Te6edf3platform Tff7b72!= Tff7b72null Tff7b72? Ta5d6ff`Tffd700${Te6edf3PLATFORM_NAMESTb4b4b4[Te6edf3infoTb4b4b4.Te6edf3platformTb4b4b4] Tff7b72|| Ta5d6ff'Unknown'Tffd700}Ta5d6ff (0xTffd700${Te6edf3infoTb4b4b4.Te6edf3platformTb4b4b4.Te6edf3toStringTb4b4b4(T79c0ff16Tb4b4b4)Tb4b4b4.Te6edf3padStartTb4b4b4(T79c0ff2Tb4b4b4,Ta5d6ff'0'Tb4b4b4)Tffd700}Ta5d6ff)Ta5d6ff` Tff7b72: Tff7b72nullTb4b4b4;
Tff7b72const Te6edf3mcuLbl Tff7b72= Te6edf3infoTb4b4b4.Te6edf3mcu Tff7b72!= Tff7b72null Tff7b72? Ta5d6ff`Tffd700${Te6edf3MCU_NAMESTb4b4b4[Te6edf3infoTb4b4b4.Te6edf3mcuTb4b4b4] Tff7b72|| Ta5d6ff'Unknown'Tffd700}Ta5d6ff (0xTffd700${Te6edf3infoTb4b4b4.Te6edf3mcuTb4b4b4.Te6edf3toStringTb4b4b4(T79c0ff16Tb4b4b4)Tb4b4b4.Te6edf3padStartTb4b4b4(T79c0ff2Tb4b4b4,Ta5d6ff'0'Tb4b4b4)Tffd700}Ta5d6ff)Ta5d6ff` Tff7b72: Tff7b72nullTb4b4b4;
Te6edf3tableTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3rowTb4b4b4(Ta5d6ff'Board'Tb4b4b4, Te6edf3boardLblTb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3tableTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3rowTb4b4b4(Ta5d6ff'Platform'Tb4b4b4, Te6edf3platLblTb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3tableTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3rowTb4b4b4(Ta5d6ff'MCU'Tb4b4b4, Te6edf3mcuLblTb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3tableTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3rowTb4b4b4(Ta5d6ff'Firmware version'Tb4b4b4, Te6edf3infoTb4b4b4.Te6edf3fwVersionTb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3infoTb4b4b4.Te6edf3devHashTb4b4b4) Te6edf3tableTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3rowTb4b4b4(Ta5d6ff'Device hash'Tb4b4b4, Te6edf3hexOfTb4b4b4(Te6edf3infoTb4b4b4.Te6edf3devHashTb4b4b4)Tb4b4b4, Ta5d6ff'hash'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3infoTb4b4b4.Te6edf3fwHashTargetTb4b4b4) Te6edf3tableTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3rowTb4b4b4(Ta5d6ff'FW hash (target)'Tb4b4b4, Te6edf3hexOfTb4b4b4(Te6edf3infoTb4b4b4.Te6edf3fwHashTargetTb4b4b4)Tb4b4b4, Ta5d6ff'hash'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3infoTb4b4b4.Te6edf3fwHashActualTb4b4b4) Te6edf3tableTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3rowTb4b4b4(Ta5d6ff'FW hash (actual)'Tb4b4b4, Te6edf3hexOfTb4b4b4(Te6edf3infoTb4b4b4.Te6edf3fwHashActualTb4b4b4)Tb4b4b4, Ta5d6ff'hash'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3infoTb4b4b4.Te6edf3bootloaderHashTb4b4b4) Te6edf3tableTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3rowTb4b4b4(Ta5d6ff'Bootloader hash'Tb4b4b4, Te6edf3hexOfTb4b4b4(Te6edf3infoTb4b4b4.Te6edf3bootloaderHashTb4b4b4)Tb4b4b4, Ta5d6ff'hash'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3infoTb4b4b4.Te6edf3partitionHashTb4b4b4) Te6edf3tableTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3rowTb4b4b4(Ta5d6ff'Partition hash'Tb4b4b4, Te6edf3hexOfTb4b4b4(Te6edf3infoTb4b4b4.Te6edf3partitionHashTb4b4b4)Tb4b4b4, Ta5d6ff'hash'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3updateTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3cleanups Tff7b72= Tb4b4b4[ Te6edf3stateTb4b4b4.Te6edf3nodeCfgDeviceInfoTb4b4b4.Te6edf3subscribeTb4b4b4(Te6edf3updateTb4b4b4) Tb4b4b4]Tb4b4b4;
Tff7b72return Tb4b4b4{ Te6edf3nodeTff7b72: Te6edf3wrapTb4b4b4, Te6edf3cleanups Tb4b4b4}Tb4b4b4;
Tb4b4b4}

Tff7b72function Te6edf3buildNcfgRadioPanelTb4b4b4(Tb4b4b4)Tb4b4b4{
T8b949e// Combined Mode + Radio panel. Mode (HOST/TNC) selector sits above the
T8b949e// radio fields. Radio config only persists for TNC mode (the HOST flow
T8b949e// re-issues radio params on every boot via individual KISS opcodes, so the
T8b949e// EEPROM-stored values are unused). Field rows are disabled when HOST is
T8b949e// selected — but kept rendered so the user sees what would be persisted.
Tff7b72const Te6edf3sec Tff7b72= Te6edf3NODE_CONFIG_SCHEMATb4b4b4.Te6edf3radioTb4b4b4;
Tff7b72const Te6edf3wrap Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'ncfg-section' Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3wrapTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'h2'Tb4b4b4, Tff7b72nullTb4b4b4, Ta5d6ff'Radio'Tb4b4b4)Tb4b4b4)Tb4b4b4;

T8b949e// Persisted mode (from EEPROM byte 0xA7). Source of truth for the Mode
T8b949e// selector's initial state. Null until EEPROM has been read.
Tff7b72const Te6edf3persistedMode Tff7b72= Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3ee Tff7b72= Te6edf3stateTb4b4b4.Te6edf3nodeCfgEepromTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3ee Tff7b72|| Te6edf3eeTb4b4b4.Te6edf3length Tff7b72<= T79c0ff0xA7Tb4b4b4) Tff7b72return Tff7b72nullTb4b4b4;
Tff7b72return Te6edf3eeTb4b4b4[T79c0ff0xA7Tb4b4b4] Tff7b72=== Te6edf3CONF_OK_BYTE Tff7b72? Ta5d6ff'tnc' Tff7b72: Ta5d6ff'host'Tb4b4b4;
Tb4b4b4}Tb4b4b4;
Tff7b72let Te6edf3targetMode Tff7b72= Te6edf3persistedModeTb4b4b4(Tb4b4b4) Tff7b72|| Ta5d6ff'host'Tb4b4b4; T8b949e// what the user has selected

T8b949e// --- Mode selector ---
Tff7b72const Te6edf3modeRow Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'mode-current'Tb4b4b4, Te6edf3styleTff7b72: Tb4b4b4{ Te6edf3displayTff7b72: Ta5d6ff'flex'Tb4b4b4, Te6edf3alignItemsTff7b72: Ta5d6ff'center'Tb4b4b4, Te6edf3gapTff7b72: Ta5d6ff'12px'Tb4b4b4, Te6edf3flexWrapTff7b72: Ta5d6ff'wrap' Tb4b4b4} Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3modeLabel Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'span'Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3modeSelect Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'select'Tb4b4b4)Tb4b4b4;
Te6edf3modeSelectTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'option'Tb4b4b4, Tb4b4b4{ Te6edf3valueTff7b72: Ta5d6ff'host' Tb4b4b4}Tb4b4b4, Ta5d6ff'HOST (KISS radio modem)'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3modeSelectTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'option'Tb4b4b4, Tb4b4b4{ Te6edf3valueTff7b72: Ta5d6ff'tnc' Tb4b4b4}Tb4b4b4, Ta5d6ff'TNC (boot into embedded RNS)'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3modeRowTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'strong'Tb4b4b4, Tff7b72nullTb4b4b4, Ta5d6ff'Boot mode: 'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3modeRowTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3modeSelectTb4b4b4)Tb4b4b4;
Te6edf3modeRowTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3modeLabelTb4b4b4)Tb4b4b4;
Te6edf3wrapTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3modeRowTb4b4b4)Tb4b4b4;

Te6edf3wrapTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'p'Tb4b4b4, Tb4b4b4{ Te6edf3styleTff7b72: Tb4b4b4{ Te6edf3colorTff7b72: Ta5d6ff'var(--muted)'Tb4b4b4, Te6edf3marginTff7b72: Ta5d6ff'8px 0 14px' Tb4b4b4} Tb4b4b4}Tb4b4b4, Tb4b4b4[
Ta5d6ff'In 'Tb4b4b4, Te6edf3elTb4b4b4(Ta5d6ff'strong'Tb4b4b4, Tff7b72nullTb4b4b4, Ta5d6ff'HOST'Tb4b4b4)Tb4b4b4, Ta5d6ff' mode the device acts as a KISS radio modem driven by this connection — radio settings are sent from the host at runtime and the EEPROM-stored values below are unused. In 'Tb4b4b4,
Te6edf3elTb4b4b4(Ta5d6ff'strong'Tb4b4b4, Tff7b72nullTb4b4b4, Ta5d6ff'TNC'Tb4b4b4)Tb4b4b4, Ta5d6ff' mode the device boots its embedded Reticulum stack and uses the radio config persisted below; the serial port carries RNS log output and the device stops responding to legacy KISS commands.'
Tb4b4b4]Tb4b4b4)Tb4b4b4)Tb4b4b4;

T8b949e// --- Toolbar ---
Tff7b72const Te6edf3toolbar Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'ns-toolbar' Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3saveBtn Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'button'Tb4b4b4, Tff7b72nullTb4b4b4, Ta5d6ff'Save Radio'Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3revertBtn Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'button'Tb4b4b4, Tff7b72nullTb4b4b4, Ta5d6ff'Revert'Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3refreshBtn Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'button'Tb4b4b4, Tff7b72nullTb4b4b4, Ta5d6ff'Refresh'Tb4b4b4)Tb4b4b4;
Te6edf3toolbarTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3saveBtnTb4b4b4)Tb4b4b4;
Te6edf3toolbarTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3revertBtnTb4b4b4)Tb4b4b4;
Te6edf3toolbarTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3refreshBtnTb4b4b4)Tb4b4b4;
Te6edf3wrapTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3toolbarTb4b4b4)Tb4b4b4;

T8b949e// --- Field rows (reused via buildFieldRow) ---
Tff7b72const Te6edf3fieldHandles Tff7b72= Tb4b4b4[Tb4b4b4]Tb4b4b4;
Tff7b72const Te6edf3fieldRows Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4)Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3f Tff7b72of Te6edf3secTb4b4b4.Te6edf3fieldsTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3h Tff7b72= Te6edf3buildFieldRowTb4b4b4(Ta5d6ff'radio'Tb4b4b4, Te6edf3fTb4b4b4, Te6edf3NCFG_CTXTb4b4b4)Tb4b4b4;
Te6edf3fieldHandlesTb4b4b4.Te6edf3pushTb4b4b4(Te6edf3hTb4b4b4)Tb4b4b4;
Te6edf3fieldRowsTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3hTb4b4b4.Te6edf3rowTb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3wrapTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3fieldRowsTb4b4b4)Tb4b4b4;

T8b949e// Find each input element so we can enable/disable based on target mode.
T8b949e// Uses querySelectorAll on the row — earlier code walked a `_children`
T8b949e// property that only exists on the self-test mock-DOM, so on real DOM the
T8b949e// loop silently no-op'd and the disable never took effect.
Tff7b72function Te6edf3setRadioFieldsEnabledTb4b4b4(Te6edf3enabledTb4b4b4)Tb4b4b4{
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3h Tff7b72of Te6edf3fieldHandlesTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3inputs Tff7b72= Te6edf3hTb4b4b4.Te6edf3rowTb4b4b4.Te6edf3querySelectorAllTb4b4b4(Ta5d6ff'input, select, textarea'Tb4b4b4)Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3inp Tff7b72of Te6edf3inputsTb4b4b4) Te6edf3inpTb4b4b4.Te6edf3disabled Tff7b72= Tff7b72!Te6edf3enabledTb4b4b4;
Tb4b4b4}
Te6edf3fieldRowsTb4b4b4.Te6edf3styleTb4b4b4.Te6edf3opacity Tff7b72= Te6edf3enabled Tff7b72? Ta5d6ff'' Tff7b72: Ta5d6ff'0.55'Tb4b4b4;
Tb4b4b4}

T8b949e// --- Auto-read EEPROM so we know the persisted mode ---
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3stateTb4b4b4.Te6edf3nodeCfgEepromTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4) Tff7b72&& Te6edf3legacyTb4b4b4) Tb4b4b4{
Te6edf3legacyTb4b4b4.Te6edf3readEepromTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3thenTb4b4b4(Te6edf3u Tb4b4b4=> Te6edf3stateTb4b4b4.Te6edf3nodeCfgEepromTb4b4b4.Te6edf3setTb4b4b4(Te6edf3uTb4b4b4)Tb4b4b4)Tb4b4b4.Tff7b72catchTb4b4b4(Te6edf3e Tb4b4b4=> Tb4b4b4{
Te6edf3consoleTb4b4b4.Te6edf3errorTb4b4b4(Ta5d6ff'Radio panel EEPROM read failed:'Tb4b4b4, Te6edf3eTb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}
T8b949e// --- Auto-fetch radio field values (custom panels skip the default
T8b949e// auto-fetch in mountSection) ---
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3stateTb4b4b4.Te6edf3nodeCfgLoadedTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4[Ta5d6ff'radio'Tb4b4b4]Tb4b4b4) Te6edf3ncfgFetchSectionTb4b4b4(Ta5d6ff'radio'Tb4b4b4)Tb4b4b4;

T8b949e// --- React to changes ---
Tff7b72function Te6edf3syncFromStateTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3pm Tff7b72= Te6edf3persistedModeTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3modeLabelTb4b4b4.Te6edf3textContent Tff7b72= Te6edf3pm Tff7b72== Tff7b72null Tff7b72? Ta5d6ff'(reading EEPROM…)'
Tff7b72: Te6edf3pm Tff7b72=== Te6edf3targetMode Tff7b72? Ta5d6ff`Ta5d6ffcurrently Tffd700${Te6edf3pmTb4b4b4.Te6edf3toUpperCaseTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff`
Tff7b72: Ta5d6ff`Ta5d6ffcurrently Tffd700${Te6edf3pmTb4b4b4.Te6edf3toUpperCaseTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff → will switch to Tffd700${Te6edf3targetModeTb4b4b4.Te6edf3toUpperCaseTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff on SaveTa5d6ff`Tb4b4b4;
T8b949e// Set select value to targetMode without firing 'change' (avoid loop)
Tff7b72if Tb4b4b4(Te6edf3modeSelectTb4b4b4.Te6edf3value Tff7b72!== Te6edf3targetModeTb4b4b4) Te6edf3modeSelectTb4b4b4.Te6edf3value Tff7b72= Te6edf3targetModeTb4b4b4;
T8b949e// Disable radio inputs when target is HOST.
Te6edf3setRadioFieldsEnabledTb4b4b4(Te6edf3targetMode Tff7b72=== Ta5d6ff'tnc'Tb4b4b4)Tb4b4b4;
Te6edf3updateButtonsTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72function Te6edf3updateButtonsTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3nsObj Tff7b72= Te6edf3stateTb4b4b4.Te6edf3nodeCfgStateTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4[Ta5d6ff'radio'Tb4b4b4] Tff7b72|| Tb4b4b4{ Te6edf3committedTff7b72: Tb4b4b4{Tb4b4b4}Tb4b4b4, Te6edf3draftTff7b72: Tb4b4b4{Tb4b4b4} Tb4b4b4}Tb4b4b4;
Tff7b72const Te6edf3hasFieldDraft Tff7b72= Tffa657ObjectTb4b4b4.Te6edf3keysTb4b4b4(Te6edf3nsObjTb4b4b4.Te6edf3draftTb4b4b4)Tb4b4b4.Te6edf3length Tff7b72> T79c0ff0Tb4b4b4;
Tff7b72const Te6edf3pm Tff7b72= Te6edf3persistedModeTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3modeChanged Tff7b72= Tb4b4b4(Te6edf3pm Tff7b72!= Tff7b72nullTb4b4b4) Tff7b72&& Tb4b4b4(Te6edf3pm Tff7b72!== Te6edf3targetModeTb4b4b4)Tb4b4b4;
T8b949e// Save is meaningful when:
T8b949e// - target=TNC AND we need to (re)write fields/conf (mode changed OR drafts)
T8b949e// - target=HOST AND we need to clear conf (mode changed from TNC)
Tff7b72const Te6edf3anyErr Tff7b72= Te6edf3fieldHandlesTb4b4b4.Te6edf3someTb4b4b4(Te6edf3h Tb4b4b4=> Te6edf3hTb4b4b4.Te6edf3hasDraftErrorTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3canSave Tff7b72= Tff7b72!Te6edf3anyErr Tff7b72&& Tb4b4b4(Tb4b4b4(Te6edf3targetMode Tff7b72=== Ta5d6ff'tnc' Tff7b72&& Tb4b4b4(Te6edf3modeChanged Tff7b72|| Te6edf3hasFieldDraftTb4b4b4)Tb4b4b4)
Tff7b72|| Tb4b4b4(Te6edf3targetMode Tff7b72=== Ta5d6ff'host' Tff7b72&& Te6edf3modeChangedTb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3saveBtnTb4b4b4.Te6edf3disabled Tff7b72= Tff7b72!Te6edf3canSaveTb4b4b4;
Te6edf3saveBtnTb4b4b4.Te6edf3classListTb4b4b4.Te6edf3toggleTb4b4b4(Ta5d6ff'primary'Tb4b4b4, Te6edf3canSaveTb4b4b4)Tb4b4b4;
Te6edf3revertBtnTb4b4b4.Te6edf3disabled Tff7b72= Tff7b72!Te6edf3hasFieldDraft Tff7b72&& Tff7b72!Te6edf3modeChangedTb4b4b4;
Tb4b4b4}
Tff7b72function Te6edf3updateFieldsTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3h Tff7b72of Te6edf3fieldHandlesTb4b4b4) Te6edf3hTb4b4b4.Te6edf3updateTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3updateButtonsTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3syncFromStateTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3updateFieldsTb4b4b4(Tb4b4b4)Tb4b4b4;

Te6edf3modeSelectTb4b4b4.Te6edf3addEventListenerTb4b4b4(Ta5d6ff'change'Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{ Te6edf3targetMode Tff7b72= Te6edf3modeSelectTb4b4b4.Te6edf3valueTb4b4b4; Te6edf3syncFromStateTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3saveBtnTb4b4b4.Te6edf3onclick Tff7b72= Tff7b72async Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3legacyTb4b4b4) Tff7b72returnTb4b4b4;
Tff7b72const Te6edf3pm Tff7b72= Te6edf3persistedModeTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72try Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3targetMode Tff7b72=== Ta5d6ff'tnc'Tb4b4b4) Tb4b4b4{
T8b949e// Confirm with the user — TNC mode means the device stops responding
T8b949e// to KISS at the next boot.
Tff7b72if Tb4b4b4(Te6edf3pm Tff7b72!== Ta5d6ff'tnc'Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3confirmTb4b4b4(Ta5d6ff'Switch to TNC mode? The device will boot into embedded RNS at the next reset and stop responding to KISS on this connection.'Tb4b4b4)Tb4b4b4) Tff7b72returnTb4b4b4;
Tb4b4b4}
T8b949e// Persist any drafted radio fields, then bring the radio online, then CMD_CONF_SAVE.
Tff7b72const Te6edf3nsObj Tff7b72= Te6edf3stateTb4b4b4.Te6edf3nodeCfgStateTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4[Ta5d6ff'radio'Tb4b4b4] Tff7b72|| Tb4b4b4{ Te6edf3committedTff7b72:Tb4b4b4{Tb4b4b4}Tb4b4b4, Te6edf3draftTff7b72:Tb4b4b4{Tb4b4b4} Tb4b4b4}Tb4b4b4;
Tff7b72if Tb4b4b4(Tffa657ObjectTb4b4b4.Te6edf3keysTb4b4b4(Te6edf3nsObjTb4b4b4.Te6edf3draftTb4b4b4)Tb4b4b4.Te6edf3length Tff7b72> T79c0ff0Tb4b4b4) Tb4b4b4{
Tff7b72await Te6edf3legacyTb4b4b4.Te6edf3writeSectionTb4b4b4(Ta5d6ff'radio'Tb4b4b4, Te6edf3nsObjTb4b4b4.Te6edf3draftTb4b4b4)Tb4b4b4;
T8b949e// Treat drafts as committed.
Te6edf3stateTb4b4b4.Te6edf3nodeCfgStateTb4b4b4.Te6edf3updateTb4b4b4(Te6edf3s Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3obj Tff7b72= Te6edf3sTb4b4b4[Ta5d6ff'radio'Tb4b4b4] Tff7b72|| Tb4b4b4{ Te6edf3committedTff7b72: Tb4b4b4{Tb4b4b4}Tb4b4b4, Te6edf3draftTff7b72: Tb4b4b4{Tb4b4b4} Tb4b4b4}Tb4b4b4;
Te6edf3sTb4b4b4[Ta5d6ff'radio'Tb4b4b4] Tff7b72= Tb4b4b4{ Te6edf3committedTff7b72: Tb4b4b4{ Tb4b4b4...Te6edf3objTb4b4b4.Te6edf3committedTb4b4b4, Tb4b4b4...Te6edf3objTb4b4b4.Te6edf3draft Tb4b4b4}Tb4b4b4, Te6edf3draftTff7b72: Tb4b4b4{Tb4b4b4} Tb4b4b4}Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3recomputeHasDraftTb4b4b4(Te6edf3NCFG_CTXTb4b4b4)Tb4b4b4;
Tb4b4b4}
T8b949e// Bring the radio online and CMD_CONF_SAVE the current lora_* values
T8b949e// to EEPROM. writeSection() above only updates RAM via per-field
T8b949e// opcodes; without this, edited values revert on the next reboot.
T8b949e// Also sets ADDR_CONF_OK so the device boots into TNC mode. Safe to
T8b949e// call even when there were no drafts — covers the mode-change-only case too.
Tff7b72await Te6edf3legacyTb4b4b4.Te6edf3setModeTb4b4b4(Tff7b72trueTb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nodeCfgNeedsRebootTb4b4b4.Te6edf3setTb4b4b4(Tff7b72trueTb4b4b4)Tb4b4b4;
Te6edf3showToastTb4b4b4(Ta5d6ff'Radio config persisted (device will boot in TNC mode)'Tb4b4b4, Ta5d6ff'warn'Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
T8b949e// Target HOST: clear TNC marker. EEPROM radio values stay but ADDR_CONF_OK=0x00.
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3confirmTb4b4b4(Ta5d6ff'Switch to HOST mode? Cleared TNC config — device boots into HOST (KISS) at the next reset.'Tb4b4b4)Tb4b4b4) Tff7b72returnTb4b4b4;
Tff7b72await Te6edf3legacyTb4b4b4.Te6edf3setModeTb4b4b4(Tff7b72falseTb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nodeCfgNeedsRebootTb4b4b4.Te6edf3setTb4b4b4(Tff7b72trueTb4b4b4)Tb4b4b4;
Te6edf3showToastTb4b4b4(Ta5d6ff'TNC config cleared — reboot to apply'Tb4b4b4, Ta5d6ff'ok'Tb4b4b4)Tb4b4b4;
Tb4b4b4}
T8b949e// Refresh EEPROM so the persisted-mode indicator updates.
Tff7b72try Tb4b4b4{ Te6edf3stateTb4b4b4.Te6edf3nodeCfgEepromTb4b4b4.Te6edf3setTb4b4b4(Tff7b72await Te6edf3legacyTb4b4b4.Te6edf3readEepromTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4}
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{
Te6edf3showToastTb4b4b4(Ta5d6ff'Save failed: ' Tff7b72+ Te6edf3eTb4b4b4.Te6edf3messageTb4b4b4, Ta5d6ff'err'Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4;
Te6edf3revertBtnTb4b4b4.Te6edf3onclick Tff7b72= Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Te6edf3stateTb4b4b4.Te6edf3nodeCfgStateTb4b4b4.Te6edf3updateTb4b4b4(Te6edf3s Tb4b4b4=> Tb4b4b4{ Tff7b72if Tb4b4b4(Te6edf3sTb4b4b4[Ta5d6ff'radio'Tb4b4b4]Tb4b4b4) Te6edf3sTb4b4b4[Ta5d6ff'radio'Tb4b4b4]Tb4b4b4.Te6edf3draft Tff7b72= Tb4b4b4{Tb4b4b4}Tb4b4b4; Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3recomputeHasDraftTb4b4b4(Te6edf3NCFG_CTXTb4b4b4)Tb4b4b4;
Te6edf3targetMode Tff7b72= Te6edf3persistedModeTb4b4b4(Tb4b4b4) Tff7b72|| Ta5d6ff'host'Tb4b4b4;
Te6edf3syncFromStateTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4;
Te6edf3refreshBtnTb4b4b4.Te6edf3onclick Tff7b72= Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Te6edf3stateTb4b4b4.Te6edf3nodeCfgLoadedTb4b4b4.Te6edf3updateTb4b4b4(Te6edf3s Tb4b4b4=> Tb4b4b4{ Tff7b72delete Te6edf3sTb4b4b4[Ta5d6ff'radio'Tb4b4b4]Tb4b4b4; Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3ncfgFetchSectionTb4b4b4(Ta5d6ff'radio'Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3legacyTb4b4b4) Te6edf3legacyTb4b4b4.Te6edf3readEepromTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3thenTb4b4b4(Te6edf3u Tb4b4b4=> Te6edf3stateTb4b4b4.Te6edf3nodeCfgEepromTb4b4b4.Te6edf3setTb4b4b4(Te6edf3uTb4b4b4)Tb4b4b4)Tb4b4b4.Tff7b72catchTb4b4b4(Tb4b4b4(Tb4b4b4)Tb4b4b4=>Tb4b4b4{Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4;

Tff7b72const Te6edf3cleanups Tff7b72= Tb4b4b4[
Te6edf3stateTb4b4b4.Te6edf3nodeCfgEepromTb4b4b4.Te6edf3subscribeTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
T8b949e// When the EEPROM read lands, default targetMode to what's persisted.
Tff7b72const Te6edf3pm Tff7b72= Te6edf3persistedModeTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3pm Tff7b72!= Tff7b72nullTb4b4b4) Te6edf3targetMode Tff7b72= Te6edf3pmTb4b4b4;
Te6edf3syncFromStateTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4,
Te6edf3stateTb4b4b4.Te6edf3nodeCfgStateTb4b4b4.Te6edf3subscribeTb4b4b4(Te6edf3updateFieldsTb4b4b4)Tb4b4b4,
Tb4b4b4]Tb4b4b4;
Tff7b72return Tb4b4b4{ Te6edf3nodeTff7b72: Te6edf3wrapTb4b4b4, Te6edf3cleanups Tb4b4b4}Tb4b4b4;
Tb4b4b4}

Tff7b72function Te6edf3buildNcfgBluetoothPanelTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3wrap Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'ncfg-section' Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3wrapTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'h2'Tb4b4b4, Tff7b72nullTb4b4b4, Ta5d6ff'Bluetooth'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3wrapTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'p'Tb4b4b4, Tb4b4b4{ Te6edf3styleTff7b72: Tb4b4b4{ Te6edf3colorTff7b72: Ta5d6ff'var(--muted)' Tb4b4b4} Tb4b4b4}Tb4b4b4,
Ta5d6ff'During pairing, the PIN appears on the device’s OLED display.'Tb4b4b4)Tb4b4b4)Tb4b4b4;

Tff7b72const Te6edf3row Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'bt-mode-row' Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3btnOff Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'button'Tb4b4b4, Tff7b72nullTb4b4b4, Ta5d6ff'Turn Off'Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3btnOn Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'button'Tb4b4b4, Tff7b72nullTb4b4b4, Ta5d6ff'Turn On'Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3btnPair Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'button'Tb4b4b4, Tff7b72nullTb4b4b4, Ta5d6ff'Enter pairing mode'Tb4b4b4)Tb4b4b4;
Te6edf3btnOffTb4b4b4.Te6edf3onclick Tff7b72= Tff7b72async Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{ Tff7b72try Tb4b4b4{ Tff7b72await Te6edf3legacyTb4b4b4.Te6edf3setBluetoothTb4b4b4(T79c0ff0Tb4b4b4)Tb4b4b4; Te6edf3showToastTb4b4b4(Ta5d6ff'Bluetooth disabled'Tb4b4b4, Ta5d6ff'ok'Tb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Te6edf3showToastTb4b4b4(Te6edf3eTb4b4b4.Te6edf3messageTb4b4b4, Ta5d6ff'err'Tb4b4b4)Tb4b4b4; Tb4b4b4} Tb4b4b4}Tb4b4b4;
Te6edf3btnOnTb4b4b4.Te6edf3onclick Tff7b72= Tff7b72async Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{ Tff7b72try Tb4b4b4{ Tff7b72await Te6edf3legacyTb4b4b4.Te6edf3setBluetoothTb4b4b4(T79c0ff1Tb4b4b4)Tb4b4b4; Te6edf3showToastTb4b4b4(Ta5d6ff'Bluetooth enabled'Tb4b4b4, Ta5d6ff'ok'Tb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Te6edf3showToastTb4b4b4(Te6edf3eTb4b4b4.Te6edf3messageTb4b4b4, Ta5d6ff'err'Tb4b4b4)Tb4b4b4; Tb4b4b4} Tb4b4b4}Tb4b4b4;
Te6edf3btnPairTb4b4b4.Te6edf3onclick Tff7b72= Tff7b72async Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{ Tff7b72try Tb4b4b4{ Tff7b72await Te6edf3legacyTb4b4b4.Te6edf3setBluetoothTb4b4b4(T79c0ff2Tb4b4b4)Tb4b4b4; Te6edf3showToastTb4b4b4(Ta5d6ff'Pairing mode active — check device display for PIN'Tb4b4b4, Ta5d6ff'ok'Tb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Te6edf3showToastTb4b4b4(Te6edf3eTb4b4b4.Te6edf3messageTb4b4b4, Ta5d6ff'err'Tb4b4b4)Tb4b4b4; Tb4b4b4} Tb4b4b4}Tb4b4b4;
Te6edf3rowTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3btnOffTb4b4b4)Tb4b4b4;
Te6edf3rowTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3btnOnTb4b4b4)Tb4b4b4;
Te6edf3rowTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3btnPairTb4b4b4)Tb4b4b4;
Te6edf3wrapTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3rowTb4b4b4)Tb4b4b4;

Tff7b72const Te6edf3danger Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'danger-zone' Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3dangerTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'h3'Tb4b4b4, Tff7b72nullTb4b4b4, Ta5d6ff'Pairing data'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3unpairBtn Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'button'Tb4b4b4, Tff7b72nullTb4b4b4, Ta5d6ff'Unpair all devices'Tb4b4b4)Tb4b4b4;
Te6edf3unpairBtnTb4b4b4.Te6edf3onclick Tff7b72= Tff7b72async Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3confirmTb4b4b4(Ta5d6ff'Remove all paired Bluetooth devices from this RNode?'Tb4b4b4)Tb4b4b4) Tff7b72returnTb4b4b4;
Tff7b72try Tb4b4b4{ Tff7b72await Te6edf3legacyTb4b4b4.Te6edf3bluetoothUnpairTb4b4b4(Tb4b4b4)Tb4b4b4; Te6edf3showToastTb4b4b4(Ta5d6ff'Unpaired all devices'Tb4b4b4, Ta5d6ff'ok'Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Te6edf3showToastTb4b4b4(Te6edf3eTb4b4b4.Te6edf3messageTb4b4b4, Ta5d6ff'err'Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4}Tb4b4b4;
Te6edf3dangerTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3unpairBtnTb4b4b4)Tb4b4b4;
Te6edf3wrapTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3dangerTb4b4b4)Tb4b4b4;
Tff7b72return Tb4b4b4{ Te6edf3nodeTff7b72: Te6edf3wrapTb4b4b4, Te6edf3cleanupsTff7b72: Tb4b4b4[Tb4b4b4] Tb4b4b4}Tb4b4b4;
Tb4b4b4}

T8b949e// Address annotations for the EEPROM hex viewer.
Tff7b72const Te6edf3EEPROM_REGIONS Tff7b72= Tb4b4b4[
Tb4b4b4{ Tff7b72fromTff7b72: T79c0ff0x00Tb4b4b4, Te6edf3toTff7b72: T79c0ff0x0ATb4b4b4, Te6edf3labelTff7b72: Ta5d6ff'Identity (product/model/HW/serial/date)' Tb4b4b4}Tb4b4b4,
Tb4b4b4{ Tff7b72fromTff7b72: T79c0ff0x9BTb4b4b4, Te6edf3toTff7b72: T79c0ff0x9BTb4b4b4, Te6edf3labelTff7b72: Ta5d6ff'INFO_LOCK' Tb4b4b4}Tb4b4b4,
Tb4b4b4{ Tff7b72fromTff7b72: T79c0ff0x9CTb4b4b4, Te6edf3toTff7b72: T79c0ff0x9CTb4b4b4, Te6edf3labelTff7b72: Ta5d6ff'SF' Tb4b4b4}Tb4b4b4,
Tb4b4b4{ Tff7b72fromTff7b72: T79c0ff0x9DTb4b4b4, Te6edf3toTff7b72: T79c0ff0x9DTb4b4b4, Te6edf3labelTff7b72: Ta5d6ff'CR' Tb4b4b4}Tb4b4b4,
Tb4b4b4{ Tff7b72fromTff7b72: T79c0ff0x9ETb4b4b4, Te6edf3toTff7b72: T79c0ff0x9ETb4b4b4, Te6edf3labelTff7b72: Ta5d6ff'TXP' Tb4b4b4}Tb4b4b4,
Tb4b4b4{ Tff7b72fromTff7b72: T79c0ff0x9FTb4b4b4, Te6edf3toTff7b72: T79c0ff0xA2Tb4b4b4, Te6edf3labelTff7b72: Ta5d6ff'BW (BE32)' Tb4b4b4}Tb4b4b4,
Tb4b4b4{ Tff7b72fromTff7b72: T79c0ff0xA3Tb4b4b4, Te6edf3toTff7b72: T79c0ff0xA6Tb4b4b4, Te6edf3labelTff7b72: Ta5d6ff'FREQ (BE32)' Tb4b4b4}Tb4b4b4,
Tb4b4b4{ Tff7b72fromTff7b72: T79c0ff0xA7Tb4b4b4, Te6edf3toTff7b72: T79c0ff0xA7Tb4b4b4, Te6edf3labelTff7b72: Ta5d6ff'CONF_OK' Tb4b4b4}Tb4b4b4,
Tb4b4b4{ Tff7b72fromTff7b72: T79c0ff0xB0Tb4b4b4, Te6edf3toTff7b72: T79c0ff0xB0Tb4b4b4, Te6edf3labelTff7b72: Ta5d6ff'BT enable' Tb4b4b4}Tb4b4b4,
Tb4b4b4{ Tff7b72fromTff7b72: T79c0ff0xB1Tb4b4b4, Te6edf3toTff7b72: T79c0ff0xB8Tb4b4b4, Te6edf3labelTff7b72: Ta5d6ff'Display' Tb4b4b4}Tb4b4b4,
Tb4b4b4{ Tff7b72fromTff7b72: T79c0ff0xB9Tb4b4b4, Te6edf3toTff7b72: T79c0ff0xB9Tb4b4b4, Te6edf3labelTff7b72: Ta5d6ff'IA disable' Tb4b4b4}Tb4b4b4,
Tb4b4b4{ Tff7b72fromTff7b72: T79c0ff0xBATb4b4b4, Te6edf3toTff7b72: T79c0ff0xBBTb4b4b4, Te6edf3labelTff7b72: Ta5d6ff'WiFi enable / channel' Tb4b4b4}Tb4b4b4,
Tb4b4b4]Tb4b4b4;

Tff7b72function Te6edf3buildHexViewTb4b4b4(Te6edf3u8Tb4b4b4, Te6edf3regionsTb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3wrap Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'hexview' Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3u8 Tff7b72|| Te6edf3u8Tb4b4b4.Te6edf3length Tff7b72=== T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3wrapTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'em'Tb4b4b4, Tb4b4b4{ Te6edf3styleTff7b72: Tb4b4b4{ Te6edf3colorTff7b72: Ta5d6ff'var(--muted)' Tb4b4b4} Tb4b4b4}Tb4b4b4, Ta5d6ff'No data — click "Read EEPROM" above.'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72return Te6edf3wrapTb4b4b4;
Tb4b4b4}
Tff7b72const Te6edf3marks Tff7b72= Tff7b72new Tffa657ArrayTb4b4b4(Te6edf3u8Tb4b4b4.Te6edf3lengthTb4b4b4)Tb4b4b4.Te6edf3fillTb4b4b4(Tff7b72falseTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tffa657ArrayTb4b4b4.Te6edf3isArrayTb4b4b4(Te6edf3regionsTb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3r Tff7b72of Te6edf3regionsTb4b4b4) Tff7b72for Tb4b4b4(Tff7b72let Te6edf3i Tff7b72= Te6edf3rTb4b4b4.Tff7b72fromTb4b4b4; Te6edf3i Tff7b72<= Te6edf3rTb4b4b4.Te6edf3to Tff7b72&& Te6edf3i Tff7b72< Te6edf3u8Tb4b4b4.Te6edf3lengthTb4b4b4; Tff7b72++Te6edf3iTb4b4b4) Te6edf3marksTb4b4b4[Te6edf3iTb4b4b4] Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4}
Tff7b72for Tb4b4b4(Tff7b72let Te6edf3off Tff7b72= T79c0ff0Tb4b4b4; Te6edf3off Tff7b72< Te6edf3u8Tb4b4b4.Te6edf3lengthTb4b4b4; Te6edf3off Tff7b72+= T79c0ff16Tb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3offStr Tff7b72= Ta5d6ff'0x' Tff7b72+ Te6edf3offTb4b4b4.Te6edf3toStringTb4b4b4(T79c0ff16Tb4b4b4)Tb4b4b4.Te6edf3padStartTb4b4b4(T79c0ff4Tb4b4b4, Ta5d6ff'0'Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3bytesEl Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'span'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'hx-bytes' Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72let Te6edf3asciiStr Tff7b72= Ta5d6ff''Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72let Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< T79c0ff16 Tff7b72&& Te6edf3off Tff7b72+ Te6edf3i Tff7b72< Te6edf3u8Tb4b4b4.Te6edf3lengthTb4b4b4; Tff7b72++Te6edf3iTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3b Tff7b72= Te6edf3u8Tb4b4b4[Te6edf3off Tff7b72+ Te6edf3iTb4b4b4]Tb4b4b4;
Tff7b72const Te6edf3span Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'span'Tb4b4b4, Te6edf3marksTb4b4b4[Te6edf3off Tff7b72+ Te6edf3iTb4b4b4] Tff7b72? Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'hx-mark' Tb4b4b4} Tff7b72: Tff7b72nullTb4b4b4, Te6edf3bTb4b4b4.Te6edf3toStringTb4b4b4(T79c0ff16Tb4b4b4)Tb4b4b4.Te6edf3padStartTb4b4b4(T79c0ff2Tb4b4b4, Ta5d6ff'0'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3bytesElTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3spanTb4b4b4)Tb4b4b4;
Te6edf3bytesElTb4b4b4.Te6edf3appendChildTb4b4b4(Tffa657documentTb4b4b4.Te6edf3createTextNodeTb4b4b4(Ta5d6ff' 'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3asciiStr Tff7b72+= Tb4b4b4(Te6edf3b Tff7b72>= T79c0ff0x20 Tff7b72&& Te6edf3b Tff7b72<= T79c0ff0x7ETb4b4b4) Tff7b72? Tffa657StringTb4b4b4.Te6edf3fromCharCodeTb4b4b4(Te6edf3bTb4b4b4) Tff7b72: Ta5d6ff'.'Tb4b4b4;
Tb4b4b4}
Tff7b72const Te6edf3row Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'hx-row' Tb4b4b4}Tb4b4b4, Tb4b4b4[
Te6edf3elTb4b4b4(Ta5d6ff'span'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'hx-off' Tb4b4b4}Tb4b4b4, Te6edf3offStrTb4b4b4)Tb4b4b4,
Te6edf3bytesElTb4b4b4,
Te6edf3elTb4b4b4(Ta5d6ff'span'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'hx-ascii' Tb4b4b4}Tb4b4b4, Ta5d6ff'|' Tff7b72+ Te6edf3asciiStr Tff7b72+ Ta5d6ff'|'Tb4b4b4)Tb4b4b4,
Tb4b4b4]Tb4b4b4)Tb4b4b4;
Te6edf3wrapTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3rowTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3regions Tff7b72&& Te6edf3regionsTb4b4b4.Te6edf3lengthTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3legend Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'hx-legend' Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3legendTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'span'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'hx-mark' Tb4b4b4}Tb4b4b4, Ta5d6ff' 'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3legendTb4b4b4.Te6edf3appendChildTb4b4b4(Tffa657documentTb4b4b4.Te6edf3createTextNodeTb4b4b4(Ta5d6ff'Highlighted bytes correspond to known config regions.'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3wrapTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3legendTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72return Te6edf3wrapTb4b4b4;
Tb4b4b4}

Tff7b72function Te6edf3downloadBlobTb4b4b4(Te6edf3nameTb4b4b4, Te6edf3dataTb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3blob Tff7b72= Tff7b72new Te6edf3BlobTb4b4b4(Tb4b4b4[Te6edf3dataTb4b4b4]Tb4b4b4, Tb4b4b4{ Te6edf3typeTff7b72: Ta5d6ff'application/octet-stream' Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3url Tff7b72= Te6edf3URLTb4b4b4.Te6edf3createObjectURLTb4b4b4(Te6edf3blobTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3a Tff7b72= Tffa657documentTb4b4b4.Te6edf3createElementTb4b4b4(Ta5d6ff'a'Tb4b4b4)Tb4b4b4;
Te6edf3aTb4b4b4.Te6edf3href Tff7b72= Te6edf3urlTb4b4b4;
Te6edf3aTb4b4b4.Te6edf3download Tff7b72= Te6edf3nameTb4b4b4;
Tffa657documentTb4b4b4.Te6edf3bodyTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3aTb4b4b4)Tb4b4b4;
Te6edf3aTb4b4b4.Te6edf3clickTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3setTimeoutTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{ Tff7b72try Tb4b4b4{ Tffa657documentTb4b4b4.Te6edf3bodyTb4b4b4.Te6edf3removeChildTb4b4b4(Te6edf3aTb4b4b4)Tb4b4b4; Te6edf3URLTb4b4b4.Te6edf3revokeObjectURLTb4b4b4(Te6edf3urlTb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4} Tb4b4b4}Tb4b4b4, T79c0ff200Tb4b4b4)Tb4b4b4;
Tb4b4b4}

Tff7b72function Te6edf3buildNcfgEepromPanelTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3wrap Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'ncfg-section' Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3wrapTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'h2'Tb4b4b4, Tff7b72nullTb4b4b4, Ta5d6ff'EEPROM'Tb4b4b4)Tb4b4b4)Tb4b4b4;

Tff7b72const Te6edf3toolbar Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'eeprom-toolbar' Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3readBtn Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'button'Tb4b4b4, Tff7b72nullTb4b4b4, Ta5d6ff'Read EEPROM'Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3readCfgBtn Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'button'Tb4b4b4, Tff7b72nullTb4b4b4, Ta5d6ff'Read WiFi config sector'Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3backupBtn Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'button'Tb4b4b4, Tff7b72nullTb4b4b4, Ta5d6ff'Backup EEPROM to file'Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3status Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'span'Tb4b4b4, Tb4b4b4{ Te6edf3styleTff7b72: Tb4b4b4{ Te6edf3colorTff7b72: Ta5d6ff'var(--muted)' Tb4b4b4} Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3readBtnTb4b4b4.Te6edf3onclick Tff7b72= Tff7b72async Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3legacyTb4b4b4) Tff7b72returnTb4b4b4;
Te6edf3readBtnTb4b4b4.Te6edf3disabled Tff7b72= Tff7b72trueTb4b4b4; Te6edf3statusTb4b4b4.Te6edf3textContent Tff7b72= Ta5d6ff'Reading EEPROM…'Tb4b4b4;
Tff7b72try Tb4b4b4{ Te6edf3stateTb4b4b4.Te6edf3nodeCfgEepromTb4b4b4.Te6edf3setTb4b4b4(Tff7b72await Te6edf3legacyTb4b4b4.Te6edf3readEepromTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4; Te6edf3statusTb4b4b4.Te6edf3textContent Tff7b72= Ta5d6ff''Tb4b4b4; Tb4b4b4}
Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Te6edf3statusTb4b4b4.Te6edf3textContent Tff7b72= Ta5d6ff''Tb4b4b4; Te6edf3showToastTb4b4b4(Ta5d6ff'EEPROM read failed: ' Tff7b72+ Te6edf3eTb4b4b4.Te6edf3messageTb4b4b4, Ta5d6ff'err'Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72finally Tb4b4b4{ Te6edf3readBtnTb4b4b4.Te6edf3disabled Tff7b72= Tff7b72falseTb4b4b4; Tb4b4b4}
Tb4b4b4}Tb4b4b4;
Te6edf3readCfgBtnTb4b4b4.Te6edf3onclick Tff7b72= Tff7b72async Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3legacyTb4b4b4) Tff7b72returnTb4b4b4;
Te6edf3readCfgBtnTb4b4b4.Te6edf3disabled Tff7b72= Tff7b72trueTb4b4b4; Te6edf3statusTb4b4b4.Te6edf3textContent Tff7b72= Ta5d6ff'Reading WiFi config sector…'Tb4b4b4;
Tff7b72try Tb4b4b4{ Te6edf3stateTb4b4b4.Te6edf3nodeCfgCfgSectorTb4b4b4.Te6edf3setTb4b4b4(Tff7b72await Te6edf3legacyTb4b4b4.Te6edf3readCfgSectorTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4; Te6edf3statusTb4b4b4.Te6edf3textContent Tff7b72= Ta5d6ff''Tb4b4b4; Tb4b4b4}
Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Te6edf3statusTb4b4b4.Te6edf3textContent Tff7b72= Ta5d6ff''Tb4b4b4; Te6edf3showToastTb4b4b4(Ta5d6ff'Config sector read failed: ' Tff7b72+ Te6edf3eTb4b4b4.Te6edf3messageTb4b4b4, Ta5d6ff'err'Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72finally Tb4b4b4{ Te6edf3readCfgBtnTb4b4b4.Te6edf3disabled Tff7b72= Tff7b72falseTb4b4b4; Tb4b4b4}
Tb4b4b4}Tb4b4b4;
Te6edf3backupBtnTb4b4b4.Te6edf3onclick Tff7b72= Tff7b72async Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3legacyTb4b4b4) Tff7b72returnTb4b4b4;
Te6edf3backupBtnTb4b4b4.Te6edf3disabled Tff7b72= Tff7b72trueTb4b4b4; Te6edf3statusTb4b4b4.Te6edf3textContent Tff7b72= Ta5d6ff'Reading EEPROM for backup…'Tb4b4b4;
Tff7b72try Tb4b4b4{
Tff7b72const Te6edf3u8 Tff7b72= Tff7b72await Te6edf3legacyTb4b4b4.Te6edf3readEepromTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nodeCfgEepromTb4b4b4.Te6edf3setTb4b4b4(Te6edf3u8Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3ts Tff7b72= Tff7b72new Tffa657DateTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3toISOStringTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3replaceTb4b4b4(Ta5d6ff/[:.]/gTb4b4b4,Ta5d6ff'-'Tb4b4b4)Tb4b4b4.Te6edf3replaceTb4b4b4(Ta5d6ff/T/Tb4b4b4,Ta5d6ff'_'Tb4b4b4)Tb4b4b4.Te6edf3sliceTb4b4b4(T79c0ff0Tb4b4b4,T79c0ff19Tb4b4b4)Tb4b4b4;
Te6edf3downloadBlobTb4b4b4(Ta5d6ff`Ta5d6ffeeprom-backup-Tffd700${Te6edf3tsTffd700}Ta5d6ff.binTa5d6ff`Tb4b4b4, Te6edf3u8Tb4b4b4)Tb4b4b4;
Te6edf3statusTb4b4b4.Te6edf3textContent Tff7b72= Ta5d6ff''Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Te6edf3statusTb4b4b4.Te6edf3textContent Tff7b72= Ta5d6ff''Tb4b4b4; Te6edf3showToastTb4b4b4(Ta5d6ff'Backup failed: ' Tff7b72+ Te6edf3eTb4b4b4.Te6edf3messageTb4b4b4, Ta5d6ff'err'Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72finally Tb4b4b4{ Te6edf3backupBtnTb4b4b4.Te6edf3disabled Tff7b72= Tff7b72falseTb4b4b4; Tb4b4b4}
Tb4b4b4}Tb4b4b4;
Te6edf3toolbarTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3readBtnTb4b4b4)Tb4b4b4;
Te6edf3toolbarTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3readCfgBtnTb4b4b4)Tb4b4b4;
Te6edf3toolbarTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3backupBtnTb4b4b4)Tb4b4b4;
Te6edf3toolbarTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3statusTb4b4b4)Tb4b4b4;
Te6edf3wrapTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3toolbarTb4b4b4)Tb4b4b4;

T8b949e// EEPROM hex view
Tff7b72const Te6edf3eeHost Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4)Tb4b4b4;
Te6edf3wrapTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'h3'Tb4b4b4, Tff7b72nullTb4b4b4, Ta5d6ff'EEPROM (reserved region, 200 bytes)'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3wrapTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3eeHostTb4b4b4)Tb4b4b4;
T8b949e// WiFi config sector hex view
Tff7b72const Te6edf3cfgHost Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4)Tb4b4b4;
Te6edf3wrapTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'h3'Tb4b4b4, Tff7b72nullTb4b4b4, Ta5d6ff'WiFi config sector (256 bytes)'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3wrapTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3cfgHostTb4b4b4)Tb4b4b4;

Tff7b72function Te6edf3updateEeTb4b4b4(Tb4b4b4)Tb4b4b4{
Te6edf3eeHostTb4b4b4.Te6edf3innerHTML Tff7b72= Ta5d6ff''Tb4b4b4;
Te6edf3eeHostTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3buildHexViewTb4b4b4(Te6edf3stateTb4b4b4.Te6edf3nodeCfgEepromTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3EEPROM_REGIONSTb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72function Te6edf3updateCfgTb4b4b4(Tb4b4b4)Tb4b4b4{
Te6edf3cfgHostTb4b4b4.Te6edf3innerHTML Tff7b72= Ta5d6ff''Tb4b4b4;
Te6edf3cfgHostTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3buildHexViewTb4b4b4(Te6edf3stateTb4b4b4.Te6edf3nodeCfgCfgSectorTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4[ Tb4b4b4{ Tff7b72fromTff7b72: T79c0ff0x00Tb4b4b4, Te6edf3toTff7b72: T79c0ff0x20Tb4b4b4, Te6edf3labelTff7b72: Ta5d6ff'SSID' Tb4b4b4}Tb4b4b4,
Tb4b4b4{ Tff7b72fromTff7b72: T79c0ff0x21Tb4b4b4, Te6edf3toTff7b72: T79c0ff0x41Tb4b4b4, Te6edf3labelTff7b72: Ta5d6ff'PSK' Tb4b4b4}Tb4b4b4,
Tb4b4b4{ Tff7b72fromTff7b72: T79c0ff0x42Tb4b4b4, Te6edf3toTff7b72: T79c0ff0x45Tb4b4b4, Te6edf3labelTff7b72: Ta5d6ff'Static IP' Tb4b4b4}Tb4b4b4,
Tb4b4b4{ Tff7b72fromTff7b72: T79c0ff0x46Tb4b4b4, Te6edf3toTff7b72: T79c0ff0x49Tb4b4b4, Te6edf3labelTff7b72: Ta5d6ff'Netmask' Tb4b4b4} Tb4b4b4]Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3updateEeTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3updateCfgTb4b4b4(Tb4b4b4)Tb4b4b4;

T8b949e// Danger zone: EEPROM wipe
Tff7b72const Te6edf3danger Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'danger-zone' Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3dangerTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'h3'Tb4b4b4, Tff7b72nullTb4b4b4, Ta5d6ff'Wipe EEPROM'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3dangerTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'p'Tb4b4b4, Tff7b72nullTb4b4b4,
Ta5d6ff'Unlocks and erases the entire 200-byte reserved EEPROM region. The device will reboot. ' Tff7b72+
Ta5d6ff'Identity bytes (product/model/HW rev/serial) are NOT preserved — you will need to re-provision the device using rnodeconf -f.'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3wipeBtn Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'button'Tb4b4b4, Tff7b72nullTb4b4b4, Ta5d6ff'Wipe EEPROM'Tb4b4b4)Tb4b4b4;
Te6edf3wipeBtnTb4b4b4.Te6edf3onclick Tff7b72= Tff7b72async Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3legacyTb4b4b4) Tff7b72returnTb4b4b4;
Tff7b72const Te6edf3typed Tff7b72= Te6edf3promptTb4b4b4(Ta5d6ff'Type WIPE in uppercase to confirm EEPROM erase:'Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3typed Tff7b72!== Ta5d6ff'WIPE'Tb4b4b4) Tb4b4b4{ Te6edf3showToastTb4b4b4(Ta5d6ff'Wipe cancelled'Tb4b4b4, Ta5d6ff'ok'Tb4b4b4)Tb4b4b4; Tff7b72returnTb4b4b4; Tb4b4b4}
Tff7b72try Tb4b4b4{
Tff7b72await Te6edf3legacyTb4b4b4.Te6edf3wipeEepromTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3showToastTb4b4b4(Ta5d6ff'EEPROM wipe sent — device is erasing and rebooting'Tb4b4b4, Ta5d6ff'warn'Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Te6edf3showToastTb4b4b4(Ta5d6ff'Wipe failed: ' Tff7b72+ Te6edf3eTb4b4b4.Te6edf3messageTb4b4b4, Ta5d6ff'err'Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4}Tb4b4b4;
Te6edf3dangerTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3wipeBtnTb4b4b4)Tb4b4b4;
Te6edf3wrapTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3dangerTb4b4b4)Tb4b4b4;

Tff7b72const Te6edf3cleanups Tff7b72= Tb4b4b4[
Te6edf3stateTb4b4b4.Te6edf3nodeCfgEepromTb4b4b4.Te6edf3subscribeTb4b4b4(Te6edf3updateEeTb4b4b4)Tb4b4b4,
Te6edf3stateTb4b4b4.Te6edf3nodeCfgCfgSectorTb4b4b4.Te6edf3subscribeTb4b4b4(Te6edf3updateCfgTb4b4b4)Tb4b4b4,
Tb4b4b4]Tb4b4b4;
Tff7b72return Tb4b4b4{ Te6edf3nodeTff7b72: Te6edf3wrapTb4b4b4, Te6edf3cleanups Tb4b4b4}Tb4b4b4;
Tb4b4b4}

Tff7b72function Te6edf3buildNodeConfigTabTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3root Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'tab-body config-tab no-pad' Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3sidenav Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'sidenav' Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3detail Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'sidenav-detail' Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3rootTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3sidenavTb4b4b4)Tb4b4b4;
Te6edf3rootTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3detailTb4b4b4)Tb4b4b4;

Tff7b72let Te6edf3secCleanups Tff7b72= Tb4b4b4[Tb4b4b4]Tb4b4b4;
Tff7b72function Te6edf3mountSectionTb4b4b4(Te6edf3sectionIdTb4b4b4)Tb4b4b4{
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3fn Tff7b72of Te6edf3secCleanupsTb4b4b4) Tb4b4b4{ Tff7b72try Tb4b4b4{ Te6edf3fnTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4} Tb4b4b4}
Te6edf3secCleanups Tff7b72= Tb4b4b4[Tb4b4b4]Tb4b4b4;
Te6edf3detailTb4b4b4.Te6edf3innerHTML Tff7b72= Ta5d6ff''Tb4b4b4;
Tff7b72const Te6edf3sec Tff7b72= Te6edf3NODE_CONFIG_SCHEMATb4b4b4[Te6edf3sectionIdTb4b4b4]Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3secTb4b4b4) Tb4b4b4{ Te6edf3detailTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'em'Tb4b4b4, Tff7b72nullTb4b4b4, Ta5d6ff'Unknown section.'Tb4b4b4)Tb4b4b4)Tb4b4b4; Tff7b72returnTb4b4b4; Tb4b4b4}
Tff7b72let Te6edf3hTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3secTb4b4b4.Te6edf3custom Tff7b72=== Ta5d6ff'device_info'Tb4b4b4) Te6edf3h Tff7b72= Te6edf3buildNcfgDeviceInfoPanelTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72else Tff7b72if Tb4b4b4(Te6edf3secTb4b4b4.Te6edf3custom Tff7b72=== Ta5d6ff'radio'Tb4b4b4) Te6edf3h Tff7b72= Te6edf3buildNcfgRadioPanelTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72else Tff7b72if Tb4b4b4(Te6edf3secTb4b4b4.Te6edf3custom Tff7b72=== Ta5d6ff'bluetooth'Tb4b4b4) Te6edf3h Tff7b72= Te6edf3buildNcfgBluetoothPanelTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72else Tff7b72if Tb4b4b4(Te6edf3secTb4b4b4.Te6edf3custom Tff7b72=== Ta5d6ff'eeprom'Tb4b4b4) Te6edf3h Tff7b72= Te6edf3buildNcfgEepromPanelTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72else Te6edf3h Tff7b72= Te6edf3buildNcfgSchemaPanelTb4b4b4(Te6edf3sectionIdTb4b4b4)Tb4b4b4;
Te6edf3secCleanups Tff7b72= Te6edf3hTb4b4b4.Te6edf3cleanupsTb4b4b4;
Te6edf3detailTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3hTb4b4b4.Te6edf3nodeTb4b4b4)Tb4b4b4;
T8b949e// For schema-driven sections, kick off an async read if not loaded yet.
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3secTb4b4b4.Te6edf3custom Tff7b72&& Tff7b72!Te6edf3stateTb4b4b4.Te6edf3nodeCfgLoadedTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4[Te6edf3sectionIdTb4b4b4]Tb4b4b4) Tb4b4b4{
Te6edf3ncfgFetchSectionTb4b4b4(Te6edf3sectionIdTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}

Tff7b72const Te6edf3navButtons Tff7b72= Tff7b72new Tffa657MapTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72function Te6edf3rebuildSidenavTb4b4b4(Tb4b4b4)Tb4b4b4{
Te6edf3sidenavTb4b4b4.Te6edf3innerHTML Tff7b72= Ta5d6ff''Tb4b4b4;
Te6edf3navButtonsTb4b4b4.Te6edf3clearTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3active Tff7b72= Te6edf3stateTb4b4b4.Te6edf3activeNodeCfgTabTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3sectionId Tff7b72of Tffa657ObjectTb4b4b4.Te6edf3keysTb4b4b4(Te6edf3NODE_CONFIG_SCHEMATb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3sec Tff7b72= Te6edf3NODE_CONFIG_SCHEMATb4b4b4[Te6edf3sectionIdTb4b4b4]Tb4b4b4;
Tff7b72const Te6edf3b Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'button'Tb4b4b4, Tb4b4b4{
Tff7b72classTff7b72: Ta5d6ff'sidenav-btn' Tff7b72+ Tb4b4b4(Te6edf3sectionId Tff7b72=== Te6edf3active Tff7b72? Ta5d6ff' active' Tff7b72: Ta5d6ff''Tb4b4b4)Tb4b4b4,
Te6edf3onclickTff7b72: Tb4b4b4(Tb4b4b4) Tb4b4b4=> Te6edf3stateTb4b4b4.Te6edf3activeNodeCfgTabTb4b4b4.Te6edf3setTb4b4b4(Te6edf3sectionIdTb4b4b4)Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3lbl Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'span'Tb4b4b4, Tff7b72nullTb4b4b4, Te6edf3secTb4b4b4.Te6edf3labelTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3dot Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'span'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'dot'Tb4b4b4, Te6edf3styleTff7b72: Tb4b4b4{ Te6edf3displayTff7b72: Te6edf3ncfgDraftCountTb4b4b4(Te6edf3sectionIdTb4b4b4) Tff7b72> T79c0ff0 Tff7b72? Ta5d6ff'' Tff7b72: Ta5d6ff'none' Tb4b4b4} Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3bTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3lblTb4b4b4)Tb4b4b4;
Te6edf3bTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3dotTb4b4b4)Tb4b4b4;
Te6edf3sidenavTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3bTb4b4b4)Tb4b4b4;
Te6edf3navButtonsTb4b4b4.Te6edf3setTb4b4b4(Te6edf3sectionIdTb4b4b4, Tb4b4b4{ Te6edf3btnTff7b72: Te6edf3bTb4b4b4, Te6edf3dot Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72function Te6edf3updateNavActiveTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3active Tff7b72= Te6edf3stateTb4b4b4.Te6edf3activeNodeCfgTabTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72const Tb4b4b4[Te6edf3sectionIdTb4b4b4, Tb4b4b4{ Te6edf3btn Tb4b4b4}Tb4b4b4] Tff7b72of Te6edf3navButtonsTb4b4b4) Te6edf3btnTb4b4b4.Te6edf3classListTb4b4b4.Te6edf3toggleTb4b4b4(Ta5d6ff'active'Tb4b4b4, Te6edf3sectionId Tff7b72=== Te6edf3activeTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72function Te6edf3updateNavDotsTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72for Tb4b4b4(Tff7b72const Tb4b4b4[Te6edf3sectionIdTb4b4b4, Tb4b4b4{ Te6edf3dot Tb4b4b4}Tb4b4b4] Tff7b72of Te6edf3navButtonsTb4b4b4) Te6edf3dotTb4b4b4.Te6edf3styleTb4b4b4.Te6edf3display Tff7b72= Te6edf3ncfgDraftCountTb4b4b4(Te6edf3sectionIdTb4b4b4) Tff7b72> T79c0ff0 Tff7b72? Ta5d6ff'' Tff7b72: Ta5d6ff'none'Tb4b4b4;
Tb4b4b4}

Te6edf3rebuildSidenavTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3mountSectionTb4b4b4(Te6edf3stateTb4b4b4.Te6edf3activeNodeCfgTabTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;

Te6edf3bodyCleanupsTb4b4b4.Te6edf3pushTb4b4b4(Te6edf3stateTb4b4b4.Te6edf3activeNodeCfgTabTb4b4b4.Te6edf3subscribeTb4b4b4(Tb4b4b4(Te6edf3idTb4b4b4) Tb4b4b4=> Tb4b4b4{ Te6edf3updateNavActiveTb4b4b4(Tb4b4b4)Tb4b4b4; Te6edf3mountSectionTb4b4b4(Te6edf3idTb4b4b4)Tb4b4b4; Tb4b4b4}Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3bodyCleanupsTb4b4b4.Te6edf3pushTb4b4b4(Te6edf3stateTb4b4b4.Te6edf3nodeCfgStateTb4b4b4.Te6edf3subscribeTb4b4b4(Te6edf3updateNavDotsTb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3bodyCleanupsTb4b4b4.Te6edf3pushTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{ Tff7b72for Tb4b4b4(Tff7b72const Te6edf3fn Tff7b72of Te6edf3secCleanupsTb4b4b4) Tff7b72try Tb4b4b4{ Te6edf3fnTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72catchTb4b4b4(Te6edf3_Tb4b4b4) Tb4b4b4{Tb4b4b4} Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72return Te6edf3rootTb4b4b4;
Tb4b4b4}

T8b949e// ----- Logs tab (persistent container) -----
Tff7b72const Te6edf3logsBuffer Tff7b72= Tb4b4b4[Tb4b4b4]Tb4b4b4;
Tff7b72const Te6edf3logsListeners Tff7b72= Tff7b72new Tffa657SetTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72let Te6edf3logsContainer Tff7b72= Tff7b72nullTb4b4b4;
Tff7b72let Te6edf3logsFollowing Tff7b72= Tff7b72trueTb4b4b4;
Tff7b72let Te6edf3logsSavedScrollTop Tff7b72= T79c0ff0Tb4b4b4;

Tff7b72function Te6edf3ensureLogsContainerTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3logsContainerTb4b4b4) Tff7b72returnTb4b4b4;
Te6edf3logsContainer Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'logs' Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3logsContainerTb4b4b4.Te6edf3addEventListenerTb4b4b4(Ta5d6ff'scroll'Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Te6edf3logsFollowing Tff7b72= Tb4b4b4(Te6edf3logsContainerTb4b4b4.Te6edf3scrollHeight Tff7b72- Te6edf3logsContainerTb4b4b4.Te6edf3scrollTop Tff7b72- Te6edf3logsContainerTb4b4b4.Te6edf3clientHeightTb4b4b4) Tff7b72< T79c0ff16Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3followPillTb4b4b4) Te6edf3followPillTb4b4b4.Te6edf3styleTb4b4b4.Te6edf3display Tff7b72= Te6edf3logsFollowing Tff7b72? Ta5d6ff'none' Tff7b72: Ta5d6ff''Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3line Tff7b72of Te6edf3logsBufferTb4b4b4) Te6edf3logsContainerTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'log-line' Tb4b4b4}Tb4b4b4, Te6edf3lineTb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3logsListenersTb4b4b4.Te6edf3addTb4b4b4(Tb4b4b4(Te6edf3newLinesTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3l Tff7b72of Te6edf3newLinesTb4b4b4) Te6edf3logsContainerTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'log-line' Tb4b4b4}Tb4b4b4, Te6edf3lTb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72while Tb4b4b4(Te6edf3logsContainerTb4b4b4.Te6edf3childNodesTb4b4b4.Te6edf3length Tff7b72> T79c0ff1000Tb4b4b4) Te6edf3logsContainerTb4b4b4.Te6edf3removeChildTb4b4b4(Te6edf3logsContainerTb4b4b4.Te6edf3firstChildTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3logsFollowing Tff7b72&& Te6edf3logsContainerTb4b4b4.Te6edf3isConnectedTb4b4b4) Te6edf3logsContainerTb4b4b4.Te6edf3scrollTop Tff7b72= Te6edf3logsContainerTb4b4b4.Te6edf3scrollHeightTb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}

Tff7b72function Te6edf3clearLogsTb4b4b4(Tb4b4b4)Tb4b4b4{
Te6edf3logsBufferTb4b4b4.Te6edf3length Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3logsContainerTb4b4b4) Tb4b4b4{
Tff7b72while Tb4b4b4(Te6edf3logsContainerTb4b4b4.Te6edf3firstChildTb4b4b4) Te6edf3logsContainerTb4b4b4.Te6edf3removeChildTb4b4b4(Te6edf3logsContainerTb4b4b4.Te6edf3firstChildTb4b4b4)Tb4b4b4;
T8b949e// After clearing, we're effectively at the bottom of an empty view — re-engage tail.
Te6edf3logsFollowing Tff7b72= Tff7b72trueTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3followPillTb4b4b4) Te6edf3followPillTb4b4b4.Te6edf3styleTb4b4b4.Te6edf3display Tff7b72= Ta5d6ff'none'Tb4b4b4;
Tb4b4b4}
Tb4b4b4}

Tff7b72let Te6edf3followPill Tff7b72= Tff7b72nullTb4b4b4;
Tff7b72function Te6edf3buildLogsTabTb4b4b4(Tb4b4b4)Tb4b4b4{
Te6edf3ensureLogsContainerTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3root Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'tab-body logs-tab no-pad' Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3toolbar Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'logs-toolbar' Tb4b4b4}Tb4b4b4, Tb4b4b4[
Te6edf3elTb4b4b4(Ta5d6ff'button'Tb4b4b4, Tb4b4b4{ Te6edf3onclickTff7b72: Te6edf3clearLogsTb4b4b4, Te6edf3titleTff7b72: Ta5d6ff'Clear the log viewer (does not affect the device)' Tb4b4b4}Tb4b4b4, Ta5d6ff'Clear'Tb4b4b4)Tb4b4b4,
Te6edf3elTb4b4b4(Ta5d6ff'span'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'spacer' Tb4b4b4}Tb4b4b4)Tb4b4b4,
Tb4b4b4]Tb4b4b4)Tb4b4b4;
Te6edf3followPill Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'button'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'follow-pill'Tb4b4b4, Te6edf3styleTff7b72: Tb4b4b4{ Te6edf3displayTff7b72: Te6edf3logsFollowing Tff7b72? Ta5d6ff'none' Tff7b72: Ta5d6ff'' Tb4b4b4}Tb4b4b4, Te6edf3onclickTff7b72: Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Te6edf3logsFollowing Tff7b72= Tff7b72trueTb4b4b4; Te6edf3followPillTb4b4b4.Te6edf3styleTb4b4b4.Te6edf3display Tff7b72= Ta5d6ff'none'Tb4b4b4;
Te6edf3logsContainerTb4b4b4.Te6edf3scrollTop Tff7b72= Te6edf3logsContainerTb4b4b4.Te6edf3scrollHeightTb4b4b4;
Tb4b4b4} Tb4b4b4}Tb4b4b4, Ta5d6ff'▼ Follow tail'Tb4b4b4)Tb4b4b4;
Te6edf3rootTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3toolbarTb4b4b4)Tb4b4b4;
Te6edf3rootTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3logsContainerTb4b4b4)Tb4b4b4;
Te6edf3rootTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3followPillTb4b4b4)Tb4b4b4;
T8b949e// Restore scroll on (re)attach. Use rAF so layout is computed before we set
T8b949e// scrollTop — queueMicrotask runs before layout and the assignment clamps to 0.
Te6edf3requestAnimationFrameTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3logsFollowingTb4b4b4) Te6edf3logsContainerTb4b4b4.Te6edf3scrollTop Tff7b72= Te6edf3logsContainerTb4b4b4.Te6edf3scrollHeightTb4b4b4;
Tff7b72else Te6edf3logsContainerTb4b4b4.Te6edf3scrollTop Tff7b72= Te6edf3logsSavedScrollTopTb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3bodyCleanupsTb4b4b4.Te6edf3pushTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
T8b949e// Save scroll position so we can restore on next mount.
Tff7b72if Tb4b4b4(Te6edf3logsContainer Tff7b72&& Te6edf3logsContainerTb4b4b4.Te6edf3isConnectedTb4b4b4) Tb4b4b4{
Te6edf3logsSavedScrollTop Tff7b72= Te6edf3logsContainerTb4b4b4.Te6edf3scrollTopTb4b4b4;
Te6edf3logsFollowing Tff7b72= Tb4b4b4(Te6edf3logsContainerTb4b4b4.Te6edf3scrollHeight Tff7b72- Te6edf3logsContainerTb4b4b4.Te6edf3scrollTop Tff7b72- Te6edf3logsContainerTb4b4b4.Te6edf3clientHeightTb4b4b4) Tff7b72< T79c0ff16Tb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72return Te6edf3rootTb4b4b4;
Tb4b4b4}

T8b949e// ----- Body switcher -----
Tff7b72function Te6edf3updateBodyTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3t Tff7b72= Te6edf3stateTb4b4b4.Te6edf3activeTabTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3bodyKey Tff7b72=== Te6edf3tTb4b4b4) Tff7b72returnTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3t Tff7b72=== Ta5d6ff'status'Tb4b4b4) Te6edf3setBodyTb4b4b4(Ta5d6ff'status'Tb4b4b4, Te6edf3buildStatusTabTb4b4b4)Tb4b4b4;
Tff7b72else Tff7b72if Tb4b4b4(Te6edf3t Tff7b72=== Ta5d6ff'nodeconfig'Tb4b4b4) Te6edf3setBodyTb4b4b4(Ta5d6ff'nodeconfig'Tb4b4b4, Te6edf3buildNodeConfigTabTb4b4b4)Tb4b4b4;
Tff7b72else Tff7b72if Tb4b4b4(Te6edf3t Tff7b72=== Ta5d6ff'config'Tb4b4b4) Te6edf3setBodyTb4b4b4(Ta5d6ff'config'Tb4b4b4, Te6edf3buildConfigTabTb4b4b4)Tb4b4b4;
Tff7b72else Tff7b72if Tb4b4b4(Te6edf3t Tff7b72=== Ta5d6ff'logs'Tb4b4b4) Te6edf3setBodyTb4b4b4(Ta5d6ff'logs'Tb4b4b4, Te6edf3buildLogsTabTb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3updateBodyTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3activeTabTb4b4b4.Te6edf3subscribeTb4b4b4(Te6edf3updateBodyTb4b4b4)Tb4b4b4;

T8b949e// ----- Bottom bar (in place) -----
Tff7b72function Te6edf3buildBottomBarTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3wrap Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4)Tb4b4b4;
Tff7b72function Te6edf3updateTb4b4b4(Tb4b4b4)Tb4b4b4{
Te6edf3wrapTb4b4b4.Te6edf3innerHTML Tff7b72= Ta5d6ff''Tb4b4b4;
Tff7b72const Te6edf3hasLocal Tff7b72= Te6edf3stateTb4b4b4.Te6edf3hasDraftTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3hasFw Tff7b72= Te6edf3stateTb4b4b4.Te6edf3firmwareHasDraftTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3hasLocal Tff7b72&& Tff7b72!Te6edf3hasFwTb4b4b4) Tff7b72returnTb4b4b4;
Tff7b72const Te6edf3drafts Tff7b72= Te6edf3stateTb4b4b4.Te6edf3nsStateTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72let Te6edf3nsCount Tff7b72= T79c0ff0Tb4b4b4, Te6edf3fieldCount Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3nsId Tff7b72in Te6edf3draftsTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3n Tff7b72= Tffa657ObjectTb4b4b4.Te6edf3keysTb4b4b4(Te6edf3draftsTb4b4b4[Te6edf3nsIdTb4b4b4]Tb4b4b4.Te6edf3draft Tff7b72|| Tb4b4b4{Tb4b4b4}Tb4b4b4)Tb4b4b4.Te6edf3lengthTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3n Tff7b72> T79c0ff0Tb4b4b4) Tb4b4b4{ Te6edf3nsCountTff7b72++Tb4b4b4; Te6edf3fieldCount Tff7b72+= Te6edf3nTb4b4b4; Tb4b4b4}
Tb4b4b4}
T8b949e// Commit and Discard operate on the firmware's staged draft, which only
T8b949e// exists once at least one namespace has been Saved. Until then, both
T8b949e// buttons are no-ops on the device side, so disable them.
Tff7b72const Te6edf3label Tff7b72= Te6edf3hasFw
Tff7b72? Ta5d6ff`Tffd700${Te6edf3fieldCountTffd700}Ta5d6ff fieldTffd700${Te6edf3fieldCount Tff7b72!== T79c0ff1 Tff7b72? Ta5d6ff's' Tff7b72: Ta5d6ff''Tffd700}Ta5d6ff pending in Tffd700${Te6edf3nsCountTffd700}Ta5d6ff namespaceTffd700${Te6edf3nsCount Tff7b72!== T79c0ff1 Tff7b72? Ta5d6ff's' Tff7b72: Ta5d6ff''Tffd700}Ta5d6ff`
Tff7b72: Ta5d6ff`Tffd700${Te6edf3fieldCountTffd700}Ta5d6ff local editTffd700${Te6edf3fieldCount Tff7b72!== T79c0ff1 Tff7b72? Ta5d6ff's' Tff7b72: Ta5d6ff''Tffd700}Ta5d6ff — save a namespace to enable Commit / DiscardTa5d6ff`Tb4b4b4;
Tff7b72const Te6edf3bar Tff7b72= Te6edf3elTb4b4b4(Ta5d6ff'div'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'bottombar' Tb4b4b4}Tb4b4b4, Tb4b4b4[
Te6edf3elTb4b4b4(Ta5d6ff'span'Tb4b4b4, Tff7b72nullTb4b4b4, Te6edf3labelTb4b4b4)Tb4b4b4,
Te6edf3elTb4b4b4(Ta5d6ff'span'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'spacer' Tb4b4b4}Tb4b4b4)Tb4b4b4,
Te6edf3elTb4b4b4(Ta5d6ff'button'Tb4b4b4, Tb4b4b4{ Te6edf3onclickTff7b72: Te6edf3discardAllTb4b4b4, Te6edf3disabledTff7b72: Tff7b72!Te6edf3hasFwTb4b4b4, Te6edf3titleTff7b72: Te6edf3hasFw Tff7b72? Ta5d6ff'' Tff7b72: Ta5d6ff'No firmware-side draft to discard' Tb4b4b4}Tb4b4b4, Ta5d6ff'Discard all'Tb4b4b4)Tb4b4b4,
Te6edf3elTb4b4b4(Ta5d6ff'button'Tb4b4b4, Tb4b4b4{ Tff7b72classTff7b72: Ta5d6ff'primary'Tb4b4b4, Te6edf3onclickTff7b72: Te6edf3commitAllTb4b4b4, Te6edf3disabledTff7b72: Tff7b72!Te6edf3hasFwTb4b4b4, Te6edf3titleTff7b72: Te6edf3hasFw Tff7b72? Ta5d6ff'' Tff7b72: Ta5d6ff'No firmware-side draft to commit' Tb4b4b4}Tb4b4b4, Ta5d6ff'Commit all'Tb4b4b4)Tb4b4b4,
Tb4b4b4]Tb4b4b4)Tb4b4b4;
Te6edf3wrapTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3barTb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3updateTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3hasDraftTb4b4b4.Te6edf3subscribeTb4b4b4(Te6edf3updateTb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3firmwareHasDraftTb4b4b4.Te6edf3subscribeTb4b4b4(Te6edf3updateTb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nsStateTb4b4b4.Te6edf3subscribeTb4b4b4(Te6edf3updateTb4b4b4)Tb4b4b4;
Tff7b72return Te6edf3wrapTb4b4b4;
Tb4b4b4}
Te6edf3slotsTb4b4b4.Te6edf3bottombarTb4b4b4.Te6edf3appendChildTb4b4b4(Te6edf3buildBottomBarTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;

T8b949e// ===== SELFTEST-BEGIN — stripped by webconsole/package.sh =====
T8b949e// ===== Self-tests =====
Tff7b72async Tff7b72function Te6edf3runSelfTestsTb4b4b4(Tb4b4b4)Tb4b4b4{
Tff7b72const Te6edf3out Tff7b72= Tb4b4b4[Tb4b4b4]Tb4b4b4;
Tff7b72const Te6edf3ok Tff7b72= Tb4b4b4(Te6edf3nTb4b4b4, Te6edf3cTb4b4b4, Te6edf3infoTb4b4b4) Tb4b4b4=> Te6edf3outTb4b4b4.Te6edf3pushTb4b4b4(Tb4b4b4(Te6edf3c Tff7b72? Ta5d6ff'OK ' Tff7b72: Ta5d6ff'FAIL'Tb4b4b4) Tff7b72+ Ta5d6ff' ' Tff7b72+ Te6edf3n Tff7b72+ Tb4b4b4(Te6edf3info Tff7b72? Ta5d6ff' [' Tff7b72+ Te6edf3info Tff7b72+ Ta5d6ff']' Tff7b72: Ta5d6ff''Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72try Tb4b4b4{
Tff7b72const Te6edf3p Tff7b72= Tff7b72new Te6edf3PackerTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3pTb4b4b4.Te6edf3arrTb4b4b4(T79c0ff3Tb4b4b4)Tb4b4b4; Te6edf3pTb4b4b4.Tff7b72intTb4b4b4(T79c0ff1Tb4b4b4)Tb4b4b4; Te6edf3pTb4b4b4.Tff7b72intTb4b4b4(T79c0ff42Tb4b4b4)Tb4b4b4;
Te6edf3pTb4b4b4.Te6edf3mapTb4b4b4(T79c0ff2Tb4b4b4)Tb4b4b4;
Te6edf3pTb4b4b4.Tff7b72intTb4b4b4(T79c0ff1Tb4b4b4)Tb4b4b4; Te6edf3pTb4b4b4.Te6edf3strTb4b4b4(Ta5d6ff'hello'Tb4b4b4)Tb4b4b4;
Te6edf3pTb4b4b4.Tff7b72intTb4b4b4(T79c0ff2Tb4b4b4)Tb4b4b4; Te6edf3pTb4b4b4.Te6edf3boolTb4b4b4(Tff7b72trueTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3u Tff7b72= Tff7b72new Te6edf3UnpackerTb4b4b4(Te6edf3pTb4b4b4.Te6edf3resultTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3v Tff7b72= Te6edf3uTb4b4b4.Te6edf3nextTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'msgpack envelope'Tb4b4b4, Tffa657ArrayTb4b4b4.Te6edf3isArrayTb4b4b4(Te6edf3vTb4b4b4) Tff7b72&& Te6edf3vTb4b4b4.Te6edf3length Tff7b72=== T79c0ff3Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'msgpack op'Tb4b4b4, Te6edf3vTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72=== T79c0ff1Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'msgpack seq'Tb4b4b4, Te6edf3vTb4b4b4[T79c0ff1Tb4b4b4] Tff7b72=== T79c0ff42Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'msgpack payload Map'Tb4b4b4, Te6edf3vTb4b4b4[T79c0ff2Tb4b4b4] Tff7b72instanceof Tffa657MapTb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'msgpack map[1]'Tb4b4b4, Te6edf3vTb4b4b4[T79c0ff2Tb4b4b4]Tb4b4b4.Te6edf3getTb4b4b4(T79c0ff1Tb4b4b4) Tff7b72=== Ta5d6ff'hello'Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'msgpack map[2]'Tb4b4b4, Te6edf3vTb4b4b4[T79c0ff2Tb4b4b4]Tb4b4b4.Te6edf3getTb4b4b4(T79c0ff2Tb4b4b4) Tff7b72=== Tff7b72trueTb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Te6edf3okTb4b4b4(Ta5d6ff'msgpack roundtrip'Tb4b4b4, Tff7b72falseTb4b4b4, Te6edf3eTb4b4b4.Te6edf3messageTb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72try Tb4b4b4{
Tff7b72const Te6edf3p2 Tff7b72= Tff7b72new Te6edf3PackerTb4b4b4(Tb4b4b4)Tb4b4b4; Te6edf3p2Tb4b4b4.Tff7b72intTb4b4b4(Tff7b72-T79c0ff300Tb4b4b4)Tb4b4b4; Te6edf3p2Tb4b4b4.Tff7b72intTb4b4b4(T79c0ff70000Tb4b4b4)Tb4b4b4; Te6edf3p2Tb4b4b4.Tff7b72floatTb4b4b4(T79c0ff3.14159265Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3u2 Tff7b72= Tff7b72new Te6edf3UnpackerTb4b4b4(Te6edf3p2Tb4b4b4.Te6edf3resultTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'msgpack int -300'Tb4b4b4, Te6edf3u2Tb4b4b4.Te6edf3nextTb4b4b4(Tb4b4b4) Tff7b72=== Tff7b72-T79c0ff300Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'msgpack uint 70000'Tb4b4b4, Te6edf3u2Tb4b4b4.Te6edf3nextTb4b4b4(Tb4b4b4) Tff7b72=== T79c0ff70000Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3f Tff7b72= Te6edf3u2Tb4b4b4.Te6edf3nextTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'msgpack float'Tb4b4b4, Tffa657MathTb4b4b4.Te6edf3absTb4b4b4(Te6edf3f Tff7b72- T79c0ff3.14159265Tb4b4b4) Tff7b72< T79c0ff1e-9Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Te6edf3okTb4b4b4(Ta5d6ff'msgpack numerics'Tb4b4b4, Tff7b72falseTb4b4b4, Te6edf3eTb4b4b4.Te6edf3messageTb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72try Tb4b4b4{
Tff7b72const Te6edf3payload Tff7b72= Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[T79c0ff0x01Tb4b4b4, Te6edf3FENDTb4b4b4, Te6edf3FESCTb4b4b4, T79c0ff0xFFTb4b4b4, Te6edf3FENDTb4b4b4, T79c0ff0x02Tb4b4b4]Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3enc Tff7b72= Te6edf3kissEncodeTb4b4b4(T79c0ff0x86Tb4b4b4, Te6edf3payloadTb4b4b4)Tb4b4b4;
Tff7b72let Te6edf3got Tff7b72= Tff7b72nullTb4b4b4;
Tff7b72const Te6edf3dec Tff7b72= Tff7b72new Te6edf3KissDecoderTb4b4b4(Tb4b4b4(Te6edf3cmdTb4b4b4, Te6edf3pTb4b4b4) Tb4b4b4=> Tb4b4b4{ Te6edf3got Tff7b72= Tb4b4b4{ Te6edf3cmdTb4b4b4, Te6edf3p Tb4b4b4}Tb4b4b4; Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3decTb4b4b4.Te6edf3feedTb4b4b4(Te6edf3encTb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'kiss cmd'Tb4b4b4, Te6edf3got Tff7b72&& Te6edf3gotTb4b4b4.Te6edf3cmd Tff7b72=== T79c0ff0x86Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'kiss payload length'Tb4b4b4, Te6edf3got Tff7b72&& Te6edf3gotTb4b4b4.Te6edf3pTb4b4b4.Te6edf3length Tff7b72=== Te6edf3payloadTb4b4b4.Te6edf3lengthTb4b4b4)Tb4b4b4;
Tff7b72let Te6edf3same Tff7b72= Tff7b72trueTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3gotTb4b4b4) Tff7b72for Tb4b4b4(Tff7b72let Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< Te6edf3payloadTb4b4b4.Te6edf3lengthTb4b4b4; Tff7b72++Te6edf3iTb4b4b4) Tff7b72if Tb4b4b4(Te6edf3gotTb4b4b4.Te6edf3pTb4b4b4[Te6edf3iTb4b4b4] Tff7b72!== Te6edf3payloadTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4) Tb4b4b4{ Te6edf3same Tff7b72= Tff7b72falseTb4b4b4; Tff7b72breakTb4b4b4; Tb4b4b4}
Te6edf3okTb4b4b4(Ta5d6ff'kiss payload bytes'Tb4b4b4, Te6edf3sameTb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Te6edf3okTb4b4b4(Ta5d6ff'kiss roundtrip'Tb4b4b4, Tff7b72falseTb4b4b4, Te6edf3eTb4b4b4.Te6edf3messageTb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72try Tb4b4b4{
Tff7b72const Te6edf3st Tff7b72= Tb4b4b4{Tb4b4b4}Tb4b4b4;
Te6edf3decodeStatusFrameTb4b4b4(T79c0ff0x27Tb4b4b4, Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[T79c0ff1Tb4b4b4, T79c0ff88Tb4b4b4]Tb4b4b4)Tb4b4b4, Te6edf3stTb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'status BAT state'Tb4b4b4, Te6edf3stTb4b4b4.Te6edf3batteryState Tff7b72=== T79c0ff1Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'status BAT %'Tb4b4b4, Te6edf3stTb4b4b4.Te6edf3batteryPercent Tff7b72=== T79c0ff88Tb4b4b4)Tb4b4b4;
Te6edf3decodeStatusFrameTb4b4b4(T79c0ff0x26Tb4b4b4, Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[T79c0ff0Tb4b4b4,T79c0ff8Tb4b4b4, T79c0ff1Tb4b4b4,T79c0ff0Tb4b4b4, T79c0ff0Tb4b4b4,T79c0ff4Tb4b4b4, T79c0ff0Tb4b4b4,T79c0ff10Tb4b4b4, T79c0ff0Tb4b4b4,T79c0ff1Tb4b4b4, T79c0ff0Tb4b4b4,T79c0ff2Tb4b4b4]Tb4b4b4)Tb4b4b4, Te6edf3stTb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'status PHYPRM symTime'Tb4b4b4, Te6edf3stTb4b4b4.Te6edf3symbolTimeUs Tff7b72=== T79c0ff8Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'status PHYPRM symRate'Tb4b4b4, Te6edf3stTb4b4b4.Te6edf3symbolRate Tff7b72=== T79c0ff256Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'status PHYPRM difs'Tb4b4b4, Te6edf3stTb4b4b4.Te6edf3difsMs Tff7b72=== T79c0ff2Tb4b4b4)Tb4b4b4;
Te6edf3decodeStatusFrameTb4b4b4(T79c0ff0x25Tb4b4b4, Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[T79c0ff0x27Tb4b4b4,T79c0ff0x10Tb4b4b4, T79c0ff0x13Tb4b4b4,T79c0ff0x88Tb4b4b4, T79c0ff0x03Tb4b4b4,T79c0ff0xE8Tb4b4b4, T79c0ff0x07Tb4b4b4,T79c0ff0xD0Tb4b4b4, T79c0ff60Tb4b4b4, T79c0ff100Tb4b4b4, T79c0ff0xFFTb4b4b4]Tb4b4b4)Tb4b4b4, Te6edf3stTb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'status CHTM airtimeShort'Tb4b4b4, Tffa657MathTb4b4b4.Te6edf3absTb4b4b4(Te6edf3stTb4b4b4.Te6edf3airtimeShort Tff7b72- T79c0ff1.0Tb4b4b4) Tff7b72< T79c0ff1e-9Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'status CHTM airtimeLong'Tb4b4b4, Tffa657MathTb4b4b4.Te6edf3absTb4b4b4(Te6edf3stTb4b4b4.Te6edf3airtimeLong Tff7b72- T79c0ff0.5Tb4b4b4) Tff7b72< T79c0ff1e-9Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'status CHTM currentRssi'Tb4b4b4, Te6edf3stTb4b4b4.Te6edf3currentRssi Tff7b72=== T79c0ff60 Tff7b72- Te6edf3RSSI_OFFSETTb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'status CHTM noiseFloor'Tb4b4b4, Te6edf3stTb4b4b4.Te6edf3noiseFloor Tff7b72=== T79c0ff100 Tff7b72- Te6edf3RSSI_OFFSETTb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'status CHTM interference null'Tb4b4b4, Te6edf3stTb4b4b4.Te6edf3interferenceRssi Tff7b72=== Tff7b72nullTb4b4b4)Tb4b4b4;
Te6edf3decodeStatusFrameTb4b4b4(T79c0ff0x23Tb4b4b4, Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[T79c0ff57Tb4b4b4]Tb4b4b4)Tb4b4b4, Te6edf3stTb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'status RSSI single'Tb4b4b4, Te6edf3stTb4b4b4.Te6edf3lastRssi Tff7b72=== T79c0ff57 Tff7b72- Te6edf3RSSI_OFFSETTb4b4b4)Tb4b4b4;
Te6edf3decodeStatusFrameTb4b4b4(T79c0ff0x24Tb4b4b4, Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[T79c0ff0xFCTb4b4b4]Tb4b4b4)Tb4b4b4, Te6edf3stTb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'status SNR signed'Tb4b4b4, Tffa657MathTb4b4b4.Te6edf3absTb4b4b4(Te6edf3stTb4b4b4.Te6edf3lastSnr Tff7b72- Tb4b4b4(Tff7b72-T79c0ff1.0Tb4b4b4)Tb4b4b4) Tff7b72< T79c0ff1e-9Tb4b4b4)Tb4b4b4;
T8b949e// CMD_STAT_TEMP: firmware adds PMU_TEMP_OFFSET=120; we subtract it back.
Te6edf3decodeStatusFrameTb4b4b4(T79c0ff0x29Tb4b4b4, Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[T79c0ff171Tb4b4b4]Tb4b4b4)Tb4b4b4, Te6edf3stTb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'status TEMP 171→51°C'Tb4b4b4, Te6edf3stTb4b4b4.Te6edf3temperatureC Tff7b72=== T79c0ff51Tb4b4b4)Tb4b4b4;
Te6edf3decodeStatusFrameTb4b4b4(T79c0ff0x29Tb4b4b4, Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[T79c0ff89Tb4b4b4]Tb4b4b4)Tb4b4b4, Te6edf3stTb4b4b4)Tb4b4b4; T8b949e// PMU_TEMP_MIN-1 sentinel
Te6edf3okTb4b4b4(Ta5d6ff'status TEMP sentinel→null'Tb4b4b4, Te6edf3stTb4b4b4.Te6edf3temperatureC Tff7b72=== Tff7b72nullTb4b4b4)Tb4b4b4;
Te6edf3decodeStatusFrameTb4b4b4(T79c0ff0x29Tb4b4b4, Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[T79c0ff145Tb4b4b4]Tb4b4b4)Tb4b4b4, Te6edf3stTb4b4b4)Tb4b4b4; T8b949e// 145 - 120 = 25°C
Te6edf3okTb4b4b4(Ta5d6ff'status TEMP 145→25°C'Tb4b4b4, Te6edf3stTb4b4b4.Te6edf3temperatureC Tff7b72=== T79c0ff25Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Te6edf3okTb4b4b4(Ta5d6ff'status decoder'Tb4b4b4, Tff7b72falseTb4b4b4, Te6edf3eTb4b4b4.Te6edf3messageTb4b4b4)Tb4b4b4; Tb4b4b4}
T8b949e// Firmware version is rendered as decimal "major.minor" (rnodeconf convention),
T8b949e// not hex. MIN_VERS=0x56 → "86", not "56".
Tff7b72try Tb4b4b4{
Tff7b72const Te6edf3fmt Tff7b72= Tb4b4b4(Te6edf3bTb4b4b4) Tb4b4b4=> Te6edf3bTb4b4b4.Te6edf3length Tff7b72>= T79c0ff2 Tff7b72? Ta5d6ff`Tffd700${Te6edf3bTb4b4b4[T79c0ff0Tb4b4b4]Tffd700}Ta5d6ff.Tffd700${Te6edf3bTb4b4b4[T79c0ff1Tb4b4b4]Tb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3padStartTb4b4b4(T79c0ff2Tb4b4b4,Ta5d6ff'0'Tb4b4b4)Tffd700}Ta5d6ff` Tff7b72: Tff7b72nullTb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'fwVersion 0x01,0x56 → 1.86'Tb4b4b4, Te6edf3fmtTb4b4b4(Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[T79c0ff0x01Tb4b4b4, T79c0ff0x56Tb4b4b4]Tb4b4b4)Tb4b4b4) Tff7b72=== Ta5d6ff'1.86'Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'fwVersion 0x02,0x0a → 2.10'Tb4b4b4, Te6edf3fmtTb4b4b4(Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[T79c0ff0x02Tb4b4b4, T79c0ff0x0aTb4b4b4]Tb4b4b4)Tb4b4b4) Tff7b72=== Ta5d6ff'2.10'Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Te6edf3okTb4b4b4(Ta5d6ff'fwVersion format'Tb4b4b4, Tff7b72falseTb4b4b4, Te6edf3eTb4b4b4.Te6edf3messageTb4b4b4)Tb4b4b4; Tb4b4b4}
T8b949e// BytesList: round-trip through MsgPack packer/unpacker.
Tff7b72try Tb4b4b4{
Tff7b72const Te6edf3a Tff7b72= Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[T79c0ff0x01Tb4b4b4,T79c0ff0x02Tb4b4b4,T79c0ff0x03Tb4b4b4,T79c0ff0x04Tb4b4b4, T79c0ff0x05Tb4b4b4,T79c0ff0x06Tb4b4b4,T79c0ff0x07Tb4b4b4,T79c0ff0x08Tb4b4b4, T79c0ff0x09Tb4b4b4,T79c0ff0x0aTb4b4b4,T79c0ff0x0bTb4b4b4,T79c0ff0x0cTb4b4b4, T79c0ff0x0dTb4b4b4,T79c0ff0x0eTb4b4b4,T79c0ff0x0fTb4b4b4,T79c0ff0x10Tb4b4b4]Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3b Tff7b72= Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[T79c0ff0xffTb4b4b4, T79c0ff0xeeTb4b4b4, T79c0ff0xddTb4b4b4, T79c0ff0xccTb4b4b4]Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3p Tff7b72= Tff7b72new Te6edf3PackerTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3packTypedValueTb4b4b4(Te6edf3pTb4b4b4, Te6edf3FTTb4b4b4.Te6edf3BytesListTb4b4b4, Tb4b4b4[Te6edf3aTb4b4b4, Te6edf3bTb4b4b4]Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3decoded Tff7b72= Tff7b72new Te6edf3UnpackerTb4b4b4(Te6edf3pTb4b4b4.Te6edf3resultTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3nextTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'BytesList round-trip is array'Tb4b4b4, Tffa657ArrayTb4b4b4.Te6edf3isArrayTb4b4b4(Te6edf3decodedTb4b4b4) Tff7b72&& Te6edf3decodedTb4b4b4.Te6edf3length Tff7b72=== T79c0ff2Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'BytesList entry 0 length'Tb4b4b4, Te6edf3decodedTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4.Te6edf3length Tff7b72=== T79c0ff16Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'BytesList entry 0 bytes'Tb4b4b4,
Te6edf3decodedTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72instanceof Tffa657Uint8Array Tff7b72&& Te6edf3decodedTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4] Tff7b72=== T79c0ff0x01 Tff7b72&& Te6edf3decodedTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff15Tb4b4b4] Tff7b72=== T79c0ff0x10Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'BytesList entry 1 bytes'Tb4b4b4,
Te6edf3decodedTb4b4b4[T79c0ff1Tb4b4b4] Tff7b72instanceof Tffa657Uint8Array Tff7b72&& Te6edf3decodedTb4b4b4[T79c0ff1Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4] Tff7b72=== T79c0ff0xff Tff7b72&& Te6edf3decodedTb4b4b4[T79c0ff1Tb4b4b4]Tb4b4b4[T79c0ff3Tb4b4b4] Tff7b72=== T79c0ff0xccTb4b4b4)Tb4b4b4;
T8b949e// Empty list
Tff7b72const Te6edf3p2 Tff7b72= Tff7b72new Te6edf3PackerTb4b4b4(Tb4b4b4)Tb4b4b4; Te6edf3packTypedValueTb4b4b4(Te6edf3p2Tb4b4b4, Te6edf3FTTb4b4b4.Te6edf3BytesListTb4b4b4, Tb4b4b4[Tb4b4b4]Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3dec2 Tff7b72= Tff7b72new Te6edf3UnpackerTb4b4b4(Te6edf3p2Tb4b4b4.Te6edf3resultTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3nextTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'BytesList empty'Tb4b4b4, Tffa657ArrayTb4b4b4.Te6edf3isArrayTb4b4b4(Te6edf3dec2Tb4b4b4) Tff7b72&& Te6edf3dec2Tb4b4b4.Te6edf3length Tff7b72=== T79c0ff0Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Te6edf3okTb4b4b4(Ta5d6ff'BytesList round-trip'Tb4b4b4, Tff7b72falseTb4b4b4, Te6edf3eTb4b4b4.Te6edf3messageTb4b4b4)Tb4b4b4; Tb4b4b4}
T8b949e// valuesEqual for BytesList
Tff7b72try Tb4b4b4{
Tff7b72const Te6edf3x1 Tff7b72= Tb4b4b4[Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[T79c0ff1Tb4b4b4,T79c0ff2Tb4b4b4,T79c0ff3Tb4b4b4]Tb4b4b4)Tb4b4b4, Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[T79c0ff4Tb4b4b4,T79c0ff5Tb4b4b4]Tb4b4b4)Tb4b4b4]Tb4b4b4;
Tff7b72const Te6edf3x2 Tff7b72= Tb4b4b4[Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[T79c0ff1Tb4b4b4,T79c0ff2Tb4b4b4,T79c0ff3Tb4b4b4]Tb4b4b4)Tb4b4b4, Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[T79c0ff4Tb4b4b4,T79c0ff5Tb4b4b4]Tb4b4b4)Tb4b4b4]Tb4b4b4;
Tff7b72const Te6edf3x3 Tff7b72= Tb4b4b4[Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[T79c0ff1Tb4b4b4,T79c0ff2Tb4b4b4,T79c0ff3Tb4b4b4]Tb4b4b4)Tb4b4b4, Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[T79c0ff4Tb4b4b4,T79c0ff6Tb4b4b4]Tb4b4b4)Tb4b4b4]Tb4b4b4;
Tff7b72const Te6edf3x4 Tff7b72= Tb4b4b4[Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[T79c0ff1Tb4b4b4,T79c0ff2Tb4b4b4,T79c0ff3Tb4b4b4]Tb4b4b4)Tb4b4b4]Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'BytesList valuesEqual same'Tb4b4b4, Te6edf3valuesEqualTb4b4b4(Te6edf3x1Tb4b4b4, Te6edf3x2Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'BytesList valuesEqual differs'Tb4b4b4, Tff7b72!Te6edf3valuesEqualTb4b4b4(Te6edf3x1Tb4b4b4, Te6edf3x3Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'BytesList valuesEqual length differs'Tb4b4b4, Tff7b72!Te6edf3valuesEqualTb4b4b4(Te6edf3x1Tb4b4b4, Te6edf3x4Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Te6edf3okTb4b4b4(Ta5d6ff'BytesList valuesEqual'Tb4b4b4, Tff7b72falseTb4b4b4, Te6edf3eTb4b4b4.Te6edf3messageTb4b4b4)Tb4b4b4; Tb4b4b4}
T8b949e// parseBytesListHex
Tff7b72try Tb4b4b4{
Tff7b72const Te6edf3r Tff7b72= Te6edf3parseBytesListHexTb4b4b4(Ta5d6ff'aabb ccdd\n11 22 33 44'Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'parseBytesListHex line count'Tb4b4b4, Te6edf3rTb4b4b4.Te6edf3length Tff7b72=== T79c0ff2Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'parseBytesListHex strips separators'Tb4b4b4,
Te6edf3rTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4.Te6edf3length Tff7b72=== T79c0ff4 Tff7b72&& Te6edf3rTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff0Tb4b4b4] Tff7b72=== T79c0ff0xaa Tff7b72&& Te6edf3rTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[T79c0ff3Tb4b4b4] Tff7b72=== T79c0ff0xddTb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'parseBytesListHex line 2 length'Tb4b4b4, Te6edf3rTb4b4b4[T79c0ff1Tb4b4b4]Tb4b4b4.Te6edf3length Tff7b72=== T79c0ff4 Tff7b72&& Te6edf3rTb4b4b4[T79c0ff1Tb4b4b4]Tb4b4b4[T79c0ff3Tb4b4b4] Tff7b72=== T79c0ff0x44Tb4b4b4)Tb4b4b4;
T8b949e// Odd hex returns null (incomplete byte)
Te6edf3okTb4b4b4(Ta5d6ff'parseBytesListHex odd nibble → null'Tb4b4b4, Te6edf3parseBytesListHexTb4b4b4(Ta5d6ff'abc'Tb4b4b4) Tff7b72=== Tff7b72nullTb4b4b4)Tb4b4b4;
T8b949e// Empty input → empty list
Te6edf3okTb4b4b4(Ta5d6ff'parseBytesListHex empty'Tb4b4b4, Tffa657ArrayTb4b4b4.Te6edf3isArrayTb4b4b4(Te6edf3parseBytesListHexTb4b4b4(Ta5d6ff''Tb4b4b4)Tb4b4b4) Tff7b72&& Te6edf3parseBytesListHexTb4b4b4(Ta5d6ff''Tb4b4b4)Tb4b4b4.Te6edf3length Tff7b72=== T79c0ff0Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Te6edf3okTb4b4b4(Ta5d6ff'parseBytesListHex'Tb4b4b4, Tff7b72falseTb4b4b4, Te6edf3eTb4b4b4.Te6edf3messageTb4b4b4)Tb4b4b4; Tb4b4b4}
T8b949e// validateValue for BytesList with constraints
Tff7b72try Tb4b4b4{
Tff7b72const Te6edf3f Tff7b72= Tb4b4b4{ Te6edf3typeTff7b72: Te6edf3FTTb4b4b4.Te6edf3BytesListTb4b4b4, Te6edf3elementSizeTff7b72: T79c0ff16Tb4b4b4, Te6edf3maxCountTff7b72: T79c0ff4 Tb4b4b4}Tb4b4b4;
Tff7b72const Te6edf3ok16 Tff7b72= Tff7b72new Tffa657Uint8ArrayTb4b4b4(T79c0ff16Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3ok16b Tff7b72= Tff7b72new Tffa657Uint8ArrayTb4b4b4(T79c0ff16Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'BytesList validate empty'Tb4b4b4, Te6edf3validateValueTb4b4b4(Te6edf3fTb4b4b4, Tb4b4b4[Tb4b4b4]Tb4b4b4) Tff7b72=== Tff7b72nullTb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'BytesList validate ok'Tb4b4b4, Te6edf3validateValueTb4b4b4(Te6edf3fTb4b4b4, Tb4b4b4[Te6edf3ok16Tb4b4b4, Te6edf3ok16bTb4b4b4]Tb4b4b4) Tff7b72=== Tff7b72nullTb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'BytesList validate too few bytes'Tb4b4b4, Te6edf3validateValueTb4b4b4(Te6edf3fTb4b4b4, Tb4b4b4[Tff7b72new Tffa657Uint8ArrayTb4b4b4(T79c0ff15Tb4b4b4)Tb4b4b4]Tb4b4b4) Tff7b72!= Tff7b72nullTb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'BytesList validate too many entries'Tb4b4b4,
Te6edf3validateValueTb4b4b4(Te6edf3fTb4b4b4, Tb4b4b4[Te6edf3ok16Tb4b4b4, Te6edf3ok16bTb4b4b4, Tff7b72new Tffa657Uint8ArrayTb4b4b4(T79c0ff16Tb4b4b4)Tb4b4b4, Tff7b72new Tffa657Uint8ArrayTb4b4b4(T79c0ff16Tb4b4b4)Tb4b4b4, Tff7b72new Tffa657Uint8ArrayTb4b4b4(T79c0ff16Tb4b4b4)Tb4b4b4]Tb4b4b4) Tff7b72!= Tff7b72nullTb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Te6edf3okTb4b4b4(Ta5d6ff'BytesList validate'Tb4b4b4, Tff7b72falseTb4b4b4, Te6edf3eTb4b4b4.Te6edf3messageTb4b4b4)Tb4b4b4; Tb4b4b4}
T8b949e// FF.WRITE_ONLY constant and renderer routing
Tff7b72try Tb4b4b4{
Te6edf3okTb4b4b4(Ta5d6ff'FF.WRITE_ONLY = 16'Tb4b4b4, Te6edf3FFTb4b4b4.Te6edf3WRITE_ONLY Tff7b72=== T79c0ff16Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'FF.READ_ONLY = 4'Tb4b4b4, Te6edf3FFTb4b4b4.Te6edf3READ_ONLY Tff7b72=== T79c0ff4Tb4b4b4)Tb4b4b4;
T8b949e// RO row renders as a static value display, never as a draft-bearing input.
Tff7b72const Te6edf3fRO Tff7b72= Tb4b4b4{ Te6edf3idTff7b72: T79c0ff99Tb4b4b4, Te6edf3nameTff7b72: Ta5d6ff'rssi_dbm'Tb4b4b4, Te6edf3labelTff7b72: Ta5d6ff'RSSI'Tb4b4b4, Te6edf3typeTff7b72: Te6edf3FTTb4b4b4.Te6edf3IntTb4b4b4, Te6edf3flagsTff7b72: Te6edf3FFTb4b4b4.Te6edf3READ_ONLY Tb4b4b4}Tb4b4b4;
Tff7b72const Te6edf3hRO Tff7b72= Te6edf3buildFieldRowTb4b4b4(T79c0ff1Tb4b4b4, Te6edf3fROTb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'RO field row class'Tb4b4b4, Te6edf3hROTb4b4b4.Te6edf3rowTb4b4b4.Te6edf3_classesTb4b4b4.Te6edf3hasTb4b4b4(Ta5d6ff'ro-info'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'RO field hasDraftError false'Tb4b4b4, Te6edf3hROTb4b4b4.Te6edf3hasDraftErrorTb4b4b4(Tb4b4b4) Tff7b72=== Tff7b72falseTb4b4b4)Tb4b4b4;
T8b949e// WO row renders input + Send button. Never participates in draft state.
Tff7b72const Te6edf3fWO Tff7b72= Tb4b4b4{ Te6edf3idTff7b72: T79c0ff100Tb4b4b4, Te6edf3nameTff7b72: Ta5d6ff'reboot_in_seconds'Tb4b4b4, Te6edf3labelTff7b72: Ta5d6ff'Reboot in (seconds)'Tb4b4b4, Te6edf3typeTff7b72: Te6edf3FTTb4b4b4.Te6edf3IntTb4b4b4, Te6edf3flagsTff7b72: Te6edf3FFTb4b4b4.Te6edf3WRITE_ONLYTb4b4b4, Te6edf3minITff7b72: T79c0ff0Tb4b4b4, Te6edf3maxITff7b72: T79c0ff60 Tb4b4b4}Tb4b4b4;
Tff7b72const Te6edf3hWO Tff7b72= Te6edf3buildFieldRowTb4b4b4(T79c0ff1Tb4b4b4, Te6edf3fWOTb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'WO field row class'Tb4b4b4, Te6edf3hWOTb4b4b4.Te6edf3rowTb4b4b4.Te6edf3_classesTb4b4b4.Te6edf3hasTb4b4b4(Ta5d6ff'wo-action'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'WO field hasDraftError false'Tb4b4b4, Te6edf3hWOTb4b4b4.Te6edf3hasDraftErrorTb4b4b4(Tb4b4b4) Tff7b72=== Tff7b72falseTb4b4b4)Tb4b4b4;
T8b949e// renderReadOnlyValue type formatting
Te6edf3okTb4b4b4(Ta5d6ff'RO Bool render true'Tb4b4b4, Te6edf3renderReadOnlyValueTb4b4b4(Tb4b4b4{ Te6edf3typeTff7b72: Te6edf3FTTb4b4b4.Te6edf3Bool Tb4b4b4}Tb4b4b4, Tff7b72trueTb4b4b4)Tb4b4b4.Te6edf3text Tff7b72=== Ta5d6ff'✓ true'Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'RO Bool render false'Tb4b4b4, Te6edf3renderReadOnlyValueTb4b4b4(Tb4b4b4{ Te6edf3typeTff7b72: Te6edf3FTTb4b4b4.Te6edf3Bool Tb4b4b4}Tb4b4b4, Tff7b72falseTb4b4b4)Tb4b4b4.Te6edf3text Tff7b72=== Ta5d6ff'✗ false'Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'RO Int+unit'Tb4b4b4, Te6edf3renderReadOnlyValueTb4b4b4(Tb4b4b4{ Te6edf3typeTff7b72: Te6edf3FTTb4b4b4.Te6edf3IntTb4b4b4, Te6edf3unitTff7b72: Ta5d6ff'dBm' Tb4b4b4}Tb4b4b4, Tff7b72-T79c0ff84Tb4b4b4)Tb4b4b4.Te6edf3text Tff7b72=== Ta5d6ff'-84 dBm'Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'RO Enum label'Tb4b4b4, Te6edf3renderReadOnlyValueTb4b4b4(Tb4b4b4{ Te6edf3typeTff7b72: Te6edf3FTTb4b4b4.Te6edf3EnumTb4b4b4, Te6edf3enumValuesTff7b72: Tb4b4b4[T79c0ff0Tb4b4b4,T79c0ff1Tb4b4b4]Tb4b4b4, Te6edf3enumLabelsTff7b72: Tb4b4b4[Ta5d6ff'off'Tb4b4b4,Ta5d6ff'on'Tb4b4b4] Tb4b4b4}Tb4b4b4, T79c0ff1Tb4b4b4)Tb4b4b4.Te6edf3text Tff7b72=== Ta5d6ff'on (1)'Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'RO Bytes hex'Tb4b4b4, Te6edf3renderReadOnlyValueTb4b4b4(Tb4b4b4{ Te6edf3typeTff7b72: Te6edf3FTTb4b4b4.Te6edf3Bytes Tb4b4b4}Tb4b4b4, Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[T79c0ff0xabTb4b4b4,T79c0ff0xcdTb4b4b4]Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3text Tff7b72=== Ta5d6ff'abcd'Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'RO Bytes empty'Tb4b4b4, Te6edf3renderReadOnlyValueTb4b4b4(Tb4b4b4{ Te6edf3typeTff7b72: Te6edf3FTTb4b4b4.Te6edf3Bytes Tb4b4b4}Tb4b4b4, Tff7b72new Tffa657Uint8ArrayTb4b4b4(T79c0ff0Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3empty Tff7b72=== Tff7b72trueTb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'RO BytesList empty'Tb4b4b4, Te6edf3renderReadOnlyValueTb4b4b4(Tb4b4b4{ Te6edf3typeTff7b72: Te6edf3FTTb4b4b4.Te6edf3BytesList Tb4b4b4}Tb4b4b4, Tb4b4b4[Tb4b4b4]Tb4b4b4)Tb4b4b4.Te6edf3empty Tff7b72=== Tff7b72trueTb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'RO null →"—"'Tb4b4b4, Te6edf3renderReadOnlyValueTb4b4b4(Tb4b4b4{ Te6edf3typeTff7b72: Te6edf3FTTb4b4b4.Te6edf3Int Tb4b4b4}Tb4b4b4, Tff7b72nullTb4b4b4)Tb4b4b4.Te6edf3empty Tff7b72=== Tff7b72trueTb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Te6edf3okTb4b4b4(Ta5d6ff'RO/WO renderers'Tb4b4b4, Tff7b72falseTb4b4b4, Te6edf3eTb4b4b4.Te6edf3messageTb4b4b4)Tb4b4b4; Tb4b4b4}
T8b949e// Namespace-tree helpers (schema v2 with parentId)
Tff7b72try Tb4b4b4{
Tff7b72const Te6edf3schema Tff7b72= Tb4b4b4{ Te6edf3namespacesTff7b72: Tb4b4b4[
Tb4b4b4{ Te6edf3idTff7b72: T79c0ff1Tb4b4b4, Te6edf3nameTff7b72: Ta5d6ff'reticulum'Tb4b4b4, Te6edf3parentIdTff7b72: T79c0ff0Tb4b4b4, Te6edf3fieldsTff7b72: Tb4b4b4[Tb4b4b4] Tb4b4b4}Tb4b4b4,
Tb4b4b4{ Te6edf3idTff7b72: T79c0ff2Tb4b4b4, Te6edf3nameTff7b72: Ta5d6ff'transport'Tb4b4b4, Te6edf3parentIdTff7b72: T79c0ff1Tb4b4b4, Te6edf3fieldsTff7b72: Tb4b4b4[Tb4b4b4] Tb4b4b4}Tb4b4b4,
Tb4b4b4{ Te6edf3idTff7b72: T79c0ff3Tb4b4b4, Te6edf3nameTff7b72: Ta5d6ff'interfaces'Tb4b4b4, Te6edf3parentIdTff7b72: T79c0ff2Tb4b4b4, Te6edf3fieldsTff7b72: Tb4b4b4[Tb4b4b4] Tb4b4b4}Tb4b4b4,
Tb4b4b4{ Te6edf3idTff7b72: T79c0ff4Tb4b4b4, Te6edf3nameTff7b72: Ta5d6ff'lora'Tb4b4b4, Te6edf3parentIdTff7b72: T79c0ff3Tb4b4b4, Te6edf3fieldsTff7b72: Tb4b4b4[Tb4b4b4] Tb4b4b4}Tb4b4b4,
Tb4b4b4{ Te6edf3idTff7b72: T79c0ff5Tb4b4b4, Te6edf3nameTff7b72: Ta5d6ff'serial'Tb4b4b4, Te6edf3parentIdTff7b72: T79c0ff3Tb4b4b4, Te6edf3fieldsTff7b72: Tb4b4b4[Tb4b4b4] Tb4b4b4}Tb4b4b4,
Tb4b4b4{ Te6edf3idTff7b72: T79c0ff101Tb4b4b4, Te6edf3nameTff7b72: Ta5d6ff'general'Tb4b4b4, Te6edf3parentIdTff7b72: T79c0ff0Tb4b4b4, Te6edf3fieldsTff7b72: Tb4b4b4[Tb4b4b4] Tb4b4b4}Tb4b4b4,
Tb4b4b4]Tb4b4b4}Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'tree: getNsById hit'Tb4b4b4, Te6edf3getNsByIdTb4b4b4(Te6edf3schemaTb4b4b4, T79c0ff4Tb4b4b4)Tb4b4b4.Te6edf3name Tff7b72=== Ta5d6ff'lora'Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'tree: getNsById miss'Tb4b4b4, Te6edf3getNsByIdTb4b4b4(Te6edf3schemaTb4b4b4, T79c0ff999Tb4b4b4) Tff7b72=== Tff7b72nullTb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'tree: roots'Tb4b4b4, Te6edf3getChildrenOfTb4b4b4(Te6edf3schemaTb4b4b4, T79c0ff0Tb4b4b4)Tb4b4b4.Te6edf3mapTb4b4b4(Te6edf3n Tb4b4b4=> Te6edf3nTb4b4b4.Te6edf3idTb4b4b4)Tb4b4b4.Te6edf3joinTb4b4b4(Ta5d6ff','Tb4b4b4) Tff7b72=== Ta5d6ff'1,101'Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'tree: children of 3'Tb4b4b4, Te6edf3getChildrenOfTb4b4b4(Te6edf3schemaTb4b4b4, T79c0ff3Tb4b4b4)Tb4b4b4.Te6edf3mapTb4b4b4(Te6edf3n Tb4b4b4=> Te6edf3nTb4b4b4.Te6edf3idTb4b4b4)Tb4b4b4.Te6edf3joinTb4b4b4(Ta5d6ff','Tb4b4b4) Tff7b72=== Ta5d6ff'4,5'Tb4b4b4)Tb4b4b4;
T8b949e// Depth-first: 1 → 2 → 3 → 4 → 5
Te6edf3okTb4b4b4(Ta5d6ff'tree: DFS of 1'Tb4b4b4, Te6edf3getNsTreeIdsTb4b4b4(Te6edf3schemaTb4b4b4, T79c0ff1Tb4b4b4)Tb4b4b4.Te6edf3joinTb4b4b4(Ta5d6ff','Tb4b4b4) Tff7b72=== Ta5d6ff'1,2,3,4,5'Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'tree: DFS of 101'Tb4b4b4, Te6edf3getNsTreeIdsTb4b4b4(Te6edf3schemaTb4b4b4, T79c0ff101Tb4b4b4)Tb4b4b4.Te6edf3joinTb4b4b4(Ta5d6ff','Tb4b4b4) Tff7b72=== Ta5d6ff'101'Tb4b4b4)Tb4b4b4;
T8b949e// Draft rollup
Te6edf3stateTb4b4b4.Te6edf3nsStateTb4b4b4.Te6edf3setTb4b4b4(Tb4b4b4{
T79c0ff1Tff7b72: Tb4b4b4{ Te6edf3committedTff7b72:Tb4b4b4{Tb4b4b4}Tb4b4b4, Te6edf3draftTff7b72:Tb4b4b4{ T79c0ff1Tff7b72: Ta5d6ff'a' Tb4b4b4} Tb4b4b4}Tb4b4b4,
T79c0ff2Tff7b72: Tb4b4b4{ Te6edf3committedTff7b72:Tb4b4b4{Tb4b4b4}Tb4b4b4, Te6edf3draftTff7b72:Tb4b4b4{Tb4b4b4} Tb4b4b4}Tb4b4b4,
T79c0ff4Tff7b72: Tb4b4b4{ Te6edf3committedTff7b72:Tb4b4b4{Tb4b4b4}Tb4b4b4, Te6edf3draftTff7b72:Tb4b4b4{ T79c0ff1Tff7b72: Ta5d6ff'x'Tb4b4b4, T79c0ff2Tff7b72: Ta5d6ff'y' Tb4b4b4} Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'tree: draft count root 1'Tb4b4b4, Te6edf3nsTreeDraftCountTb4b4b4(Te6edf3schemaTb4b4b4, T79c0ff1Tb4b4b4) Tff7b72=== T79c0ff3Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'tree: draft count root 101'Tb4b4b4, Te6edf3nsTreeDraftCountTb4b4b4(Te6edf3schemaTb4b4b4, T79c0ff101Tb4b4b4) Tff7b72=== T79c0ff0Tb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nsStateTb4b4b4.Te6edf3setTb4b4b4(Tb4b4b4{Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Te6edf3okTb4b4b4(Ta5d6ff'tree helpers'Tb4b4b4, Tff7b72falseTb4b4b4, Te6edf3eTb4b4b4.Te6edf3messageTb4b4b4)Tb4b4b4; Tb4b4b4}
T8b949e// Schema parser: v2 layout [id, name, parent_id, fields]
Tff7b72try Tb4b4b4{
T8b949e// Build a synthetic GetSchema response and parse it via a stub client.
Tff7b72const Te6edf3sched Tff7b72= Tb4b4b4(Te6edf3entriesTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3u Tff7b72= Te6edf3entriesTb4b4b4; T8b949e// already a Map-based decoded body
Tff7b72const Te6edf3namespaces Tff7b72= Tb4b4b4[Tb4b4b4]Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3nsEntry Tff7b72of Te6edf3uTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Tffa657ArrayTb4b4b4.Te6edf3isArrayTb4b4b4(Te6edf3nsEntryTb4b4b4) Tff7b72|| Te6edf3nsEntryTb4b4b4.Te6edf3length Tff7b72< T79c0ff3Tb4b4b4) Tff7b72continueTb4b4b4;
Tff7b72const Te6edf3v2 Tff7b72= Te6edf3nsEntryTb4b4b4.Te6edf3length Tff7b72>= T79c0ff4Tb4b4b4;
Tff7b72const Te6edf3parentId Tff7b72= Te6edf3v2 Tff7b72? Tffa657NumberTb4b4b4(Te6edf3nsEntryTb4b4b4[T79c0ff2Tb4b4b4] Tff7b72|| T79c0ff0Tb4b4b4) Tff7b72: T79c0ff0Tb4b4b4;
Tff7b72const Te6edf3fieldsRaw Tff7b72= Te6edf3v2 Tff7b72? Te6edf3nsEntryTb4b4b4[T79c0ff3Tb4b4b4] Tff7b72: Te6edf3nsEntryTb4b4b4[T79c0ff2Tb4b4b4]Tb4b4b4;
Te6edf3namespacesTb4b4b4.Te6edf3pushTb4b4b4(Tb4b4b4{ Te6edf3idTff7b72: Tffa657NumberTb4b4b4(Te6edf3nsEntryTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4)Tb4b4b4, Te6edf3nameTff7b72: Tffa657StringTb4b4b4(Te6edf3nsEntryTb4b4b4[T79c0ff1Tb4b4b4]Tb4b4b4)Tb4b4b4, Te6edf3parentIdTb4b4b4, Te6edf3fieldsTff7b72: Tffa657ArrayTb4b4b4.Te6edf3isArrayTb4b4b4(Te6edf3fieldsRawTb4b4b4) Tff7b72? Te6edf3fieldsRaw Tff7b72: Tb4b4b4[Tb4b4b4] Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72return Te6edf3namespacesTb4b4b4;
Tb4b4b4}Tb4b4b4;
T8b949e// v2 entry: [1, 'reticulum', 0, []]
Tff7b72const Te6edf3v2parsed Tff7b72= Te6edf3schedTb4b4b4(Tb4b4b4[Tb4b4b4[T79c0ff1Tb4b4b4, Ta5d6ff'reticulum'Tb4b4b4, T79c0ff0Tb4b4b4, Tb4b4b4[Tb4b4b4]Tb4b4b4]Tb4b4b4]Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'schema v2 parses parentId=0'Tb4b4b4, Te6edf3v2parsedTb4b4b4.Te6edf3length Tff7b72=== T79c0ff1 Tff7b72&& Te6edf3v2parsedTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4.Te6edf3parentId Tff7b72=== T79c0ff0Tb4b4b4)Tb4b4b4;
T8b949e// v2 entry with non-zero parentId: [2, 'transport', 1, []]
Tff7b72const Te6edf3v2child Tff7b72= Te6edf3schedTb4b4b4(Tb4b4b4[Tb4b4b4[T79c0ff2Tb4b4b4, Ta5d6ff'transport'Tb4b4b4, T79c0ff1Tb4b4b4, Tb4b4b4[Tb4b4b4]Tb4b4b4]Tb4b4b4]Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'schema v2 parses parentId=1'Tb4b4b4, Te6edf3v2childTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4.Te6edf3parentId Tff7b72=== T79c0ff1Tb4b4b4)Tb4b4b4;
T8b949e// v1 entry: [42, 'legacy', []]
Tff7b72const Te6edf3v1parsed Tff7b72= Te6edf3schedTb4b4b4(Tb4b4b4[Tb4b4b4[T79c0ff42Tb4b4b4, Ta5d6ff'legacy'Tb4b4b4, Tb4b4b4[Tb4b4b4]Tb4b4b4]Tb4b4b4]Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'schema v1 back-compat'Tb4b4b4, Te6edf3v1parsedTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4.Te6edf3parentId Tff7b72=== T79c0ff0 Tff7b72&& Tffa657ArrayTb4b4b4.Te6edf3isArrayTb4b4b4(Te6edf3v1parsedTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4.Te6edf3fieldsTb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Te6edf3okTb4b4b4(Ta5d6ff'schema parser'Tb4b4b4, Tff7b72falseTb4b4b4, Te6edf3eTb4b4b4.Te6edf3messageTb4b4b4)Tb4b4b4; Tb4b4b4}
T8b949e// Multi-level nesting: panel for "Metrics" should show "Interfaces" as a
T8b949e// depth-1 section (h3) and "LoRa" as a depth-2 sub-section (h4), with
T8b949e// distinct CSS classes and indent values.
Tff7b72try Tb4b4b4{
Tff7b72const Te6edf3schema Tff7b72= Tb4b4b4{ Te6edf3namespacesTff7b72: Tb4b4b4[
Tb4b4b4{ Te6edf3idTff7b72: T79c0ff4Tb4b4b4, Te6edf3nameTff7b72: Ta5d6ff'Metrics'Tb4b4b4, Te6edf3parentIdTff7b72: T79c0ff0Tb4b4b4, Te6edf3fieldsTff7b72: Tb4b4b4[Tb4b4b4] Tb4b4b4}Tb4b4b4,
Tb4b4b4{ Te6edf3idTff7b72: T79c0ff5Tb4b4b4, Te6edf3nameTff7b72: Ta5d6ff'Interfaces'Tb4b4b4, Te6edf3parentIdTff7b72: T79c0ff4Tb4b4b4, Te6edf3fieldsTff7b72: Tb4b4b4[Tb4b4b4] Tb4b4b4}Tb4b4b4,
Tb4b4b4{ Te6edf3idTff7b72: T79c0ff6Tb4b4b4, Te6edf3nameTff7b72: Ta5d6ff'LoRa'Tb4b4b4, Te6edf3parentIdTff7b72: T79c0ff5Tb4b4b4, Te6edf3fieldsTff7b72: Tb4b4b4[Tb4b4b4] Tb4b4b4}Tb4b4b4,
Tb4b4b4]Tb4b4b4}Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3schemaTb4b4b4.Te6edf3setTb4b4b4(Te6edf3schemaTb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nsStateTb4b4b4.Te6edf3setTb4b4b4(Tb4b4b4{ T79c0ff4Tff7b72:Tb4b4b4{Te6edf3committedTff7b72:Tb4b4b4{Tb4b4b4}Tb4b4b4,Te6edf3draftTff7b72:Tb4b4b4{Tb4b4b4}Tb4b4b4}Tb4b4b4, T79c0ff5Tff7b72:Tb4b4b4{Te6edf3committedTff7b72:Tb4b4b4{Tb4b4b4}Tb4b4b4,Te6edf3draftTff7b72:Tb4b4b4{Tb4b4b4}Tb4b4b4}Tb4b4b4, T79c0ff6Tff7b72:Tb4b4b4{Te6edf3committedTff7b72:Tb4b4b4{Tb4b4b4}Tb4b4b4,Te6edf3draftTff7b72:Tb4b4b4{Tb4b4b4}Tb4b4b4} Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3stateTb4b4b4.Te6edf3nsLoadedTb4b4b4.Te6edf3setTb4b4b4(Tb4b4b4{ T79c0ff4Tff7b72:Tff7b72trueTb4b4b4, T79c0ff5Tff7b72:Tff7b72trueTb4b4b4, T79c0ff6Tff7b72:Tff7b72true Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72const Tb4b4b4{ Te6edf3node Tb4b4b4} Tff7b72= Te6edf3buildNamespacePanelTb4b4b4(T79c0ff4Tb4b4b4)Tb4b4b4;
T8b949e// Walk the rendered node to find each heading.
Tff7b72let Te6edf3h2Tff7b72=Tff7b72nullTb4b4b4, Te6edf3h3Tff7b72=Tff7b72nullTb4b4b4, Te6edf3h4Tff7b72=Tff7b72nullTb4b4b4;
Tb4b4b4(Tff7b72function Te6edf3walkTb4b4b4(Te6edf3nTb4b4b4)Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3nTb4b4b4) Tff7b72returnTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3nTb4b4b4.Te6edf3tagName Tff7b72=== Ta5d6ff'h2' Tff7b72&& Te6edf3nTb4b4b4.Te6edf3_classes Tff7b72&& Te6edf3nTb4b4b4.Te6edf3_classesTb4b4b4.Te6edf3hasTb4b4b4(Ta5d6ff'ns-h'Tb4b4b4)Tb4b4b4) Te6edf3h2 Tff7b72= Te6edf3nTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3nTb4b4b4.Te6edf3tagName Tff7b72=== Ta5d6ff'h3' Tff7b72&& Te6edf3nTb4b4b4.Te6edf3_classes Tff7b72&& Te6edf3nTb4b4b4.Te6edf3_classesTb4b4b4.Te6edf3hasTb4b4b4(Ta5d6ff'ns-sub'Tb4b4b4)Tb4b4b4) Te6edf3h3 Tff7b72= Te6edf3nTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3nTb4b4b4.Te6edf3tagName Tff7b72=== Ta5d6ff'h4' Tff7b72&& Te6edf3nTb4b4b4.Te6edf3_classes Tff7b72&& Te6edf3nTb4b4b4.Te6edf3_classesTb4b4b4.Te6edf3hasTb4b4b4(Ta5d6ff'ns-sub'Tb4b4b4)Tb4b4b4) Te6edf3h4 Tff7b72= Te6edf3nTb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3c Tff7b72of Tb4b4b4(Te6edf3nTb4b4b4.Te6edf3_childrenTff7b72||Tb4b4b4[Tb4b4b4]Tb4b4b4)Tb4b4b4) Te6edf3walkTb4b4b4(Te6edf3cTb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4(Te6edf3nodeTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3text Tff7b72= Tb4b4b4(Te6edf3nTb4b4b4) Tb4b4b4=> Te6edf3n Tff7b72? Tb4b4b4(Te6edf3nTb4b4b4.Te6edf3_childrenTff7b72||Tb4b4b4[Tb4b4b4]Tb4b4b4)Tb4b4b4.Te6edf3filterTb4b4b4(Te6edf3c Tb4b4b4=> Te6edf3c Tff7b72&& Te6edf3cTb4b4b4.Te6edf3nodeType Tff7b72=== T79c0ff3Tb4b4b4)Tb4b4b4.Te6edf3mapTb4b4b4(Te6edf3c Tb4b4b4=> Te6edf3cTb4b4b4.Te6edf3textContentTb4b4b4)Tb4b4b4.Te6edf3joinTb4b4b4(Ta5d6ff''Tb4b4b4) Tff7b72: Ta5d6ff''Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'depth-0 root h2 "Metrics"'Tb4b4b4, Tff7b72!Tff7b72!Te6edf3h2 Tff7b72&& Te6edf3textTb4b4b4(Te6edf3h2Tb4b4b4) Tff7b72=== Ta5d6ff'Metrics'Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'depth-1 "Interfaces" → h3'Tb4b4b4, Tff7b72!Tff7b72!Te6edf3h3 Tff7b72&& Te6edf3textTb4b4b4(Te6edf3h3Tb4b4b4) Tff7b72=== Ta5d6ff'Interfaces'Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'depth-1 has depth-1 class'Tb4b4b4, Tff7b72!Tff7b72!Te6edf3h3 Tff7b72&& Te6edf3h3Tb4b4b4.Te6edf3_classesTb4b4b4.Te6edf3hasTb4b4b4(Ta5d6ff'depth-1'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'depth-2 "LoRa" → h4'Tb4b4b4, Tff7b72!Tff7b72!Te6edf3h4 Tff7b72&& Te6edf3textTb4b4b4(Te6edf3h4Tb4b4b4) Tff7b72=== Ta5d6ff'LoRa'Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'depth-2 has depth-2 class'Tb4b4b4, Tff7b72!Tff7b72!Te6edf3h4 Tff7b72&& Te6edf3h4Tb4b4b4.Te6edf3_classesTb4b4b4.Te6edf3hasTb4b4b4(Ta5d6ff'depth-2'Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'depth-1 indent 0px'Tb4b4b4, Tff7b72!Tff7b72!Te6edf3h3 Tff7b72&& Te6edf3h3Tb4b4b4.Te6edf3style Tff7b72&& Te6edf3h3Tb4b4b4.Te6edf3styleTb4b4b4.Te6edf3marginLeft Tff7b72=== Ta5d6ff'0px'Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'depth-2 indent 16px'Tb4b4b4, Tff7b72!Tff7b72!Te6edf3h4 Tff7b72&& Te6edf3h4Tb4b4b4.Te6edf3style Tff7b72&& Te6edf3h4Tb4b4b4.Te6edf3styleTb4b4b4.Te6edf3marginLeft Tff7b72=== Ta5d6ff'16px'Tb4b4b4)Tb4b4b4;
T8b949e// Cleanup
Te6edf3stateTb4b4b4.Te6edf3schemaTb4b4b4.Te6edf3setTb4b4b4(Tff7b72nullTb4b4b4)Tb4b4b4; Te6edf3stateTb4b4b4.Te6edf3nsStateTb4b4b4.Te6edf3setTb4b4b4(Tb4b4b4{Tb4b4b4}Tb4b4b4)Tb4b4b4; Te6edf3stateTb4b4b4.Te6edf3nsLoadedTb4b4b4.Te6edf3setTb4b4b4(Tb4b4b4{Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Te6edf3okTb4b4b4(Ta5d6ff'multi-level nesting'Tb4b4b4, Tff7b72falseTb4b4b4, Te6edf3eTb4b4b4.Te6edf3messageTb4b4b4)Tb4b4b4; Tb4b4b4}
T8b949e// WiFi readFn: decode SSID/PSK/IP/NM from a synthetic CONFIG sector, and
T8b949e// mode/channel from a synthetic main-EEPROM image. This is the read path
T8b949e// that lets the Refresh button (and post-reboot reload) display actual
T8b949e// persisted values instead of falling back to schema defaults.
Tff7b72try Tb4b4b4{
Tff7b72const Te6edf3wifi Tff7b72= Te6edf3NODE_CONFIG_SCHEMATb4b4b4.Te6edf3wifiTb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'WiFi schema has readFn'Tb4b4b4, Tff7b72typeof Te6edf3wifiTb4b4b4.Te6edf3readFn Tff7b72=== Ta5d6ff'function'Tb4b4b4)Tb4b4b4;
T8b949e// Synthetic CONFIG sector: SSID="MyNet", PSK="hunter2", IP=192.168.1.42, NM=255.255.255.0
Tff7b72const Te6edf3cfg Tff7b72= Tff7b72new Tffa657Uint8ArrayTb4b4b4(T79c0ff256Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3ssid Tff7b72= Tff7b72new Te6edf3TextEncoderTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3encodeTb4b4b4(Ta5d6ff'MyNet'Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3psk Tff7b72= Tff7b72new Te6edf3TextEncoderTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3encodeTb4b4b4(Ta5d6ff'hunter2'Tb4b4b4)Tb4b4b4;
Te6edf3cfgTb4b4b4.Te6edf3setTb4b4b4(Te6edf3ssidTb4b4b4, T79c0ff0x00Tb4b4b4)Tb4b4b4; T8b949e// SSID at 0x00 (null-terminated by the surrounding zeros)
Te6edf3cfgTb4b4b4.Te6edf3setTb4b4b4(Te6edf3pskTb4b4b4, T79c0ff0x21Tb4b4b4)Tb4b4b4; T8b949e// PSK at 0x21
Te6edf3cfgTb4b4b4[T79c0ff0x42Tb4b4b4] Tff7b72= T79c0ff192Tb4b4b4; Te6edf3cfgTb4b4b4[T79c0ff0x43Tb4b4b4] Tff7b72= T79c0ff168Tb4b4b4; Te6edf3cfgTb4b4b4[T79c0ff0x44Tb4b4b4] Tff7b72= T79c0ff1Tb4b4b4; Te6edf3cfgTb4b4b4[T79c0ff0x45Tb4b4b4] Tff7b72= T79c0ff42Tb4b4b4;
Te6edf3cfgTb4b4b4[T79c0ff0x46Tb4b4b4] Tff7b72= T79c0ff255Tb4b4b4; Te6edf3cfgTb4b4b4[T79c0ff0x47Tb4b4b4] Tff7b72= T79c0ff255Tb4b4b4; Te6edf3cfgTb4b4b4[T79c0ff0x48Tb4b4b4] Tff7b72= T79c0ff255Tb4b4b4; Te6edf3cfgTb4b4b4[T79c0ff0x49Tb4b4b4] Tff7b72= T79c0ff0Tb4b4b4;
T8b949e// Synthetic main EEPROM: mode=STA(1) at 0xBA, channel=6 at 0xBB.
Tff7b72const Te6edf3ee Tff7b72= Tff7b72new Tffa657Uint8ArrayTb4b4b4(T79c0ff200Tb4b4b4)Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72let Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< T79c0ff200Tb4b4b4; Tff7b72++Te6edf3iTb4b4b4) Te6edf3eeTb4b4b4[Te6edf3iTb4b4b4] Tff7b72= T79c0ff0xFFTb4b4b4; T8b949e// simulate uninitialised
Te6edf3eeTb4b4b4[T79c0ff0xBATb4b4b4] Tff7b72= T79c0ff0x01Tb4b4b4; Te6edf3eeTb4b4b4[T79c0ff0xBBTb4b4b4] Tff7b72= T79c0ff0x06Tb4b4b4;
Tff7b72const Te6edf3stubLegacy Tff7b72= Tb4b4b4{ Te6edf3readCfgSectorTff7b72: Tff7b72async Tb4b4b4(Tb4b4b4) Tb4b4b4=> Te6edf3cfgTb4b4b4, Te6edf3readEepromTff7b72: Tff7b72async Tb4b4b4(Tb4b4b4) Tb4b4b4=> Te6edf3ee Tb4b4b4}Tb4b4b4;
Tff7b72const Te6edf3out Tff7b72= Tff7b72await Te6edf3wifiTb4b4b4.Te6edf3readFnTb4b4b4(Te6edf3stubLegacyTb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'WiFi readFn ssid'Tb4b4b4, Te6edf3outTb4b4b4.Te6edf3ssid Tff7b72=== Ta5d6ff'MyNet'Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'WiFi readFn psk'Tb4b4b4, Te6edf3outTb4b4b4.Te6edf3psk Tff7b72=== Ta5d6ff'hunter2'Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'WiFi readFn ip'Tb4b4b4, Te6edf3outTb4b4b4.Te6edf3ip Tff7b72=== Ta5d6ff'192.168.1.42'Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'WiFi readFn nm'Tb4b4b4, Te6edf3outTb4b4b4.Te6edf3nm Tff7b72=== Ta5d6ff'255.255.255.0'Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'WiFi readFn mode'Tb4b4b4, Te6edf3outTb4b4b4.Te6edf3mode Tff7b72=== T79c0ff0x01Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'WiFi readFn channel'Tb4b4b4, Te6edf3outTb4b4b4.Te6edf3channel Tff7b72=== T79c0ff6Tb4b4b4)Tb4b4b4;
T8b949e// Uninitialised EEPROM ⇒ no SSID/PSK exposed and no mode/channel surfaced.
Tff7b72const Te6edf3fresh Tff7b72= Tff7b72new Tffa657Uint8ArrayTb4b4b4(T79c0ff256Tb4b4b4)Tb4b4b4.Te6edf3fillTb4b4b4(T79c0ff0xFFTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3ee2 Tff7b72= Tff7b72new Tffa657Uint8ArrayTb4b4b4(T79c0ff200Tb4b4b4)Tb4b4b4.Te6edf3fillTb4b4b4(T79c0ff0xFFTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3out2 Tff7b72= Tff7b72await Te6edf3wifiTb4b4b4.Te6edf3readFnTb4b4b4(Tb4b4b4{ Te6edf3readCfgSectorTff7b72: Tff7b72async Tb4b4b4(Tb4b4b4) Tb4b4b4=> Te6edf3freshTb4b4b4, Te6edf3readEepromTff7b72: Tff7b72async Tb4b4b4(Tb4b4b4) Tb4b4b4=> Te6edf3ee2 Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'WiFi readFn fresh ssid empty'Tb4b4b4, Te6edf3out2Tb4b4b4.Te6edf3ssid Tff7b72=== Ta5d6ff''Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'WiFi readFn fresh ip = DHCP'Tb4b4b4, Te6edf3out2Tb4b4b4.Te6edf3ip Tff7b72=== Ta5d6ff'0.0.0.0'Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'WiFi readFn fresh mode absent'Tb4b4b4, Tff7b72!Tb4b4b4(Ta5d6ff'mode' Tff7b72in Te6edf3out2Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'WiFi readFn fresh channel absent'Tb4b4b4,Tff7b72!Tb4b4b4(Ta5d6ff'channel' Tff7b72in Te6edf3out2Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Te6edf3okTb4b4b4(Ta5d6ff'WiFi readFn'Tb4b4b4, Tff7b72falseTb4b4b4, Te6edf3eTb4b4b4.Te6edf3messageTb4b4b4)Tb4b4b4; Tb4b4b4}
T8b949e// ----- Node Config codec round-trips -----
Tff7b72try Tb4b4b4{
T8b949e// be32 frequency encode/decode (867500000 Hz = 0x33B4FFE0)
Tff7b72const Te6edf3freq Tff7b72= Te6edf3NCFG_ENCTb4b4b4.Te6edf3be32Tb4b4b4.Te6edf3encTb4b4b4(T79c0ff867500000Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'ncfg be32 enc length'Tb4b4b4, Te6edf3freqTb4b4b4.Te6edf3length Tff7b72=== T79c0ff4Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'ncfg be32 enc bytes'Tb4b4b4, Te6edf3freqTb4b4b4[T79c0ff0Tb4b4b4]Tff7b72===T79c0ff0x33 Tff7b72&& Te6edf3freqTb4b4b4[T79c0ff1Tb4b4b4]Tff7b72===T79c0ff0xB4 Tff7b72&& Te6edf3freqTb4b4b4[T79c0ff2Tb4b4b4]Tff7b72===T79c0ff0xFF Tff7b72&& Te6edf3freqTb4b4b4[T79c0ff3Tb4b4b4]Tff7b72===T79c0ff0xE0Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'ncfg be32 dec'Tb4b4b4, Te6edf3NCFG_ENCTb4b4b4.Te6edf3be32Tb4b4b4.Te6edf3decTb4b4b4(Te6edf3freqTb4b4b4) Tff7b72=== T79c0ff867500000Tb4b4b4)Tb4b4b4;
T8b949e// u8 SF
Te6edf3okTb4b4b4(Ta5d6ff'ncfg u8 enc'Tb4b4b4, Te6edf3NCFG_ENCTb4b4b4.Te6edf3u8Tb4b4b4.Te6edf3encTb4b4b4(T79c0ff7Tb4b4b4)Tb4b4b4[T79c0ff0Tb4b4b4] Tff7b72=== T79c0ff7Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'ncfg u8 dec'Tb4b4b4, Te6edf3NCFG_ENCTb4b4b4.Te6edf3u8Tb4b4b4.Te6edf3decTb4b4b4(Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[T79c0ff12Tb4b4b4]Tb4b4b4)Tb4b4b4) Tff7b72=== T79c0ff12Tb4b4b4)Tb4b4b4;
T8b949e// i8 TXP signed
Te6edf3okTb4b4b4(Ta5d6ff'ncfg i8 enc -9'Tb4b4b4, Te6edf3NCFG_ENCTb4b4b4.Te6edf3i8Tb4b4b4.Te6edf3encTb4b4b4(Tff7b72-T79c0ff9Tb4b4b4)Tb4b4b4[T79c0ff0Tb4b4b4] Tff7b72=== Tb4b4b4(T79c0ff256 Tff7b72- T79c0ff9Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'ncfg i8 dec -1'Tb4b4b4, Te6edf3NCFG_ENCTb4b4b4.Te6edf3i8Tb4b4b4.Te6edf3decTb4b4b4(Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[T79c0ff0xFFTb4b4b4]Tb4b4b4)Tb4b4b4) Tff7b72=== Tff7b72-T79c0ff1Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'ncfg i8 dec 22'Tb4b4b4, Te6edf3NCFG_ENCTb4b4b4.Te6edf3i8Tb4b4b4.Te6edf3decTb4b4b4(Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[T79c0ff22Tb4b4b4]Tb4b4b4)Tb4b4b4) Tff7b72=== T79c0ff22Tb4b4b4)Tb4b4b4;
T8b949e// str null-terminated
Tff7b72const Te6edf3sBytes Tff7b72= Te6edf3NCFG_ENCTb4b4b4.Te6edf3strTb4b4b4.Te6edf3encStrTb4b4b4(Ta5d6ff'hello'Tb4b4b4, T79c0ff32Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'ncfg str null-term'Tb4b4b4, Te6edf3sBytesTb4b4b4.Te6edf3length Tff7b72=== T79c0ff6 Tff7b72&& Te6edf3sBytesTb4b4b4[T79c0ff5Tb4b4b4] Tff7b72=== T79c0ff0Tb4b4b4)Tb4b4b4;
T8b949e// ip4 round-trip
Tff7b72const Te6edf3ip Tff7b72= Te6edf3NCFG_ENCTb4b4b4.Te6edf3ip4Tb4b4b4.Te6edf3encTb4b4b4(Ta5d6ff'192.168.1.42'Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'ncfg ip4 enc'Tb4b4b4, Te6edf3ipTb4b4b4[T79c0ff0Tb4b4b4]Tff7b72===T79c0ff192 Tff7b72&& Te6edf3ipTb4b4b4[T79c0ff1Tb4b4b4]Tff7b72===T79c0ff168 Tff7b72&& Te6edf3ipTb4b4b4[T79c0ff2Tb4b4b4]Tff7b72===T79c0ff1 Tff7b72&& Te6edf3ipTb4b4b4[T79c0ff3Tb4b4b4]Tff7b72===T79c0ff42Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'ncfg ip4 dec'Tb4b4b4, Te6edf3NCFG_ENCTb4b4b4.Te6edf3ip4Tb4b4b4.Te6edf3decTb4b4b4(Te6edf3ipTb4b4b4) Tff7b72=== Ta5d6ff'192.168.1.42'Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'ncfg ip4 DHCP zero'Tb4b4b4, Te6edf3NCFG_ENCTb4b4b4.Te6edf3ip4Tb4b4b4.Te6edf3decTb4b4b4(Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[T79c0ff0Tb4b4b4,T79c0ff0Tb4b4b4,T79c0ff0Tb4b4b4,T79c0ff0Tb4b4b4]Tb4b4b4)Tb4b4b4) Tff7b72=== Ta5d6ff'0.0.0.0'Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Te6edf3okTb4b4b4(Ta5d6ff'ncfg codec'Tb4b4b4, Tff7b72falseTb4b4b4, Te6edf3eTb4b4b4.Te6edf3messageTb4b4b4)Tb4b4b4; Tb4b4b4}
T8b949e// KISS-frame assembly for the legacy opcodes
Tff7b72try Tb4b4b4{
T8b949e// BT_CTRL "on" → FEND 0x46 0x01 FEND
Tff7b72const Te6edf3f Tff7b72= Te6edf3kissEncodeTb4b4b4(Te6edf3CMD_BT_CTRLTb4b4b4, Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[T79c0ff0x01Tb4b4b4]Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'ncfg BT_CTRL frame'Tb4b4b4, Te6edf3fTb4b4b4.Te6edf3length Tff7b72=== T79c0ff4 Tff7b72&& Te6edf3fTb4b4b4[T79c0ff0Tb4b4b4]Tff7b72===T79c0ff0xC0 Tff7b72&& Te6edf3fTb4b4b4[T79c0ff1Tb4b4b4]Tff7b72===T79c0ff0x46 Tff7b72&& Te6edf3fTb4b4b4[T79c0ff2Tb4b4b4]Tff7b72===T79c0ff0x01 Tff7b72&& Te6edf3fTb4b4b4[T79c0ff3Tb4b4b4]Tff7b72===T79c0ff0xC0Tb4b4b4)Tb4b4b4;
T8b949e// CMD_CONF_SAVE with empty payload → FEND 0x53 FEND
Tff7b72const Te6edf3cs Tff7b72= Te6edf3kissEncodeTb4b4b4(Te6edf3CMD_CONF_SAVETb4b4b4, Tff7b72new Tffa657Uint8ArrayTb4b4b4(T79c0ff0Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'ncfg CMD_CONF_SAVE frame'Tb4b4b4, Te6edf3csTb4b4b4.Te6edf3length Tff7b72=== T79c0ff3 Tff7b72&& Te6edf3csTb4b4b4[T79c0ff0Tb4b4b4]Tff7b72===T79c0ff0xC0 Tff7b72&& Te6edf3csTb4b4b4[T79c0ff1Tb4b4b4]Tff7b72===T79c0ff0x53 Tff7b72&& Te6edf3csTb4b4b4[T79c0ff2Tb4b4b4]Tff7b72===T79c0ff0xC0Tb4b4b4)Tb4b4b4;
T8b949e// CMD_UNLOCK_ROM with magic byte
Tff7b72const Te6edf3ur Tff7b72= Te6edf3kissEncodeTb4b4b4(Te6edf3CMD_UNLOCK_ROMTb4b4b4, Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[Te6edf3ROM_UNLOCK_BYTETb4b4b4]Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'ncfg ROM unlock frame'Tb4b4b4, Te6edf3urTb4b4b4.Te6edf3length Tff7b72=== T79c0ff4 Tff7b72&& Te6edf3urTb4b4b4[T79c0ff1Tb4b4b4]Tff7b72===T79c0ff0x59 Tff7b72&& Te6edf3urTb4b4b4[T79c0ff2Tb4b4b4]Tff7b72===T79c0ff0xF8Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Te6edf3okTb4b4b4(Ta5d6ff'ncfg frames'Tb4b4b4, Tff7b72falseTb4b4b4, Te6edf3eTb4b4b4.Te6edf3messageTb4b4b4)Tb4b4b4; Tb4b4b4}
T8b949e// LegacyClient.query() round-trip via a synthetic transport.
Tff7b72try Tb4b4b4{
Tff7b72const Te6edf3sent Tff7b72= Tb4b4b4[Tb4b4b4]Tb4b4b4;
Tff7b72const Te6edf3fakeT Tff7b72= Tb4b4b4{ Te6edf3sendTff7b72: Tff7b72async Tb4b4b4(Te6edf3bTb4b4b4) Tb4b4b4=> Tb4b4b4{ Te6edf3sentTb4b4b4.Te6edf3pushTb4b4b4(Te6edf3bTb4b4b4)Tb4b4b4; Tb4b4b4}Tb4b4b4, Te6edf3onBytesTff7b72: Tb4b4b4(Tb4b4b4)Tb4b4b4=>Tb4b4b4{Tb4b4b4} Tb4b4b4}Tb4b4b4;
Tff7b72const Te6edf3fakeProv Tff7b72= Tb4b4b4{ Te6edf3onLegacyFrameTff7b72: Tff7b72nullTb4b4b4, Te6edf3_onFrameTff7b72: Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{Tb4b4b4} Tb4b4b4}Tb4b4b4;
Tff7b72const Te6edf3lc Tff7b72= Tff7b72new Te6edf3LegacyClientTb4b4b4(Te6edf3fakeProvTb4b4b4, Te6edf3fakeTTb4b4b4)Tb4b4b4;
Tff7b72let Te6edf3resolvedVal Tff7b72= Tff7b72nullTb4b4b4;
Te6edf3lcTb4b4b4.Te6edf3queryTb4b4b4(Te6edf3CMD_FREQUENCYTb4b4b4, Te6edf3NCFG_ENCTb4b4b4.Te6edf3be32Tb4b4b4.Te6edf3queryTb4b4b4(Tb4b4b4)Tb4b4b4, T79c0ff1000Tb4b4b4)Tb4b4b4.Te6edf3thenTb4b4b4(Te6edf3p Tb4b4b4=> Tb4b4b4{ Te6edf3resolvedVal Tff7b72= Te6edf3NCFG_ENCTb4b4b4.Te6edf3be32Tb4b4b4.Te6edf3decTb4b4b4(Te6edf3pTb4b4b4)Tb4b4b4; Tb4b4b4}Tb4b4b4)Tb4b4b4;
T8b949e// Yield once so the lc.query's send() promise can land its handler.
Tff7b72await Tffa657PromiseTb4b4b4.Te6edf3resolveTb4b4b4(Tb4b4b4)Tb4b4b4;
T8b949e// Simulate the device's echoed response by invoking onLegacyFrame.
Te6edf3fakeProvTb4b4b4.Te6edf3onLegacyFrameTb4b4b4(Te6edf3CMD_FREQUENCYTb4b4b4, Tff7b72new Tffa657Uint8ArrayTb4b4b4(Tb4b4b4[T79c0ff0x33Tb4b4b4, T79c0ff0xB4Tb4b4b4, T79c0ff0xFFTb4b4b4, T79c0ff0xE0Tb4b4b4]Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72await Tffa657PromiseTb4b4b4.Te6edf3resolveTb4b4b4(Tb4b4b4)Tb4b4b4; Tff7b72await Tffa657PromiseTb4b4b4.Te6edf3resolveTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'LegacyClient query echo'Tb4b4b4, Te6edf3resolvedVal Tff7b72=== T79c0ff867500000Tb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'LegacyClient query sent one frame'Tb4b4b4, Te6edf3sentTb4b4b4.Te6edf3length Tff7b72=== T79c0ff1Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Te6edf3okTb4b4b4(Ta5d6ff'LegacyClient query'Tb4b4b4, Tff7b72falseTb4b4b4, Te6edf3eTb4b4b4.Te6edf3messageTb4b4b4)Tb4b4b4; Tb4b4b4}
T8b949e// Hex-viewer rendering
Tff7b72try Tb4b4b4{
Tff7b72const Te6edf3u Tff7b72= Tff7b72new Tffa657Uint8ArrayTb4b4b4(T79c0ff32Tb4b4b4)Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72let Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< T79c0ff32Tb4b4b4; Tff7b72++Te6edf3iTb4b4b4) Te6edf3uTb4b4b4[Te6edf3iTb4b4b4] Tff7b72= Te6edf3iTb4b4b4;
Tff7b72const Te6edf3view Tff7b72= Te6edf3buildHexViewTb4b4b4(Te6edf3uTb4b4b4, Tb4b4b4[Tb4b4b4{ Tff7b72fromTff7b72: T79c0ff0x9CTb4b4b4, Te6edf3toTff7b72: T79c0ff0x9CTb4b4b4, Te6edf3labelTff7b72: Ta5d6ff'SF' Tb4b4b4}Tb4b4b4]Tb4b4b4)Tb4b4b4;
T8b949e// Top-level wrapper has class hexview; should contain 2 rows (16-byte each)
Tff7b72let Te6edf3rowCount Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72function Te6edf3walkTb4b4b4(Te6edf3nTb4b4b4) Tb4b4b4{ Tff7b72if Tb4b4b4(Tff7b72!Te6edf3n Tff7b72|| Tff7b72!Te6edf3nTb4b4b4.Te6edf3_childrenTb4b4b4) Tff7b72returnTb4b4b4; Tff7b72for Tb4b4b4(Tff7b72const Te6edf3c Tff7b72of Te6edf3nTb4b4b4.Te6edf3_childrenTb4b4b4) Tb4b4b4{ Tff7b72if Tb4b4b4(Te6edf3cTb4b4b4.Te6edf3_classes Tff7b72&& Te6edf3cTb4b4b4.Te6edf3_classesTb4b4b4.Te6edf3has Tff7b72&& Te6edf3cTb4b4b4.Te6edf3_classesTb4b4b4.Te6edf3hasTb4b4b4(Ta5d6ff'hx-row'Tb4b4b4)Tb4b4b4) Te6edf3rowCountTff7b72++Tb4b4b4; Te6edf3walkTb4b4b4(Te6edf3cTb4b4b4)Tb4b4b4; Tb4b4b4} Tb4b4b4}
Te6edf3walkTb4b4b4(Te6edf3viewTb4b4b4)Tb4b4b4;
Te6edf3okTb4b4b4(Ta5d6ff'hexview row count'Tb4b4b4, Te6edf3rowCount Tff7b72=== T79c0ff2Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Te6edf3okTb4b4b4(Ta5d6ff'hexview'Tb4b4b4, Tff7b72falseTb4b4b4, Te6edf3eTb4b4b4.Te6edf3messageTb4b4b4)Tb4b4b4; Tb4b4b4}
Tffa657documentTb4b4b4.Te6edf3getElementByIdTb4b4b4(Ta5d6ff'app'Tb4b4b4)Tb4b4b4.Te6edf3innerHTML Tff7b72= Ta5d6ff'<pre>' Tff7b72+ Te6edf3outTb4b4b4.Te6edf3joinTb4b4b4(Ta5d6ff'\n'Tb4b4b4) Tff7b72+ Ta5d6ff'</pre>'Tb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3locationTb4b4b4.Te6edf3searchTb4b4b4.Te6edf3indexOfTb4b4b4(Ta5d6ff'selftest=1'Tb4b4b4) Tff7b72!== Tff7b72-T79c0ff1Tb4b4b4) Te6edf3runSelfTestsTb4b4b4(Tb4b4b4)Tb4b4b4;
T8b949e// ===== SELFTEST-END =====
Tb4b4b4}Tb4b4b4)Tb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4<Tb4b4b4/Tff7b72scriptTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72bodyTb4b4b4>
Tb4b4b4<Tb4b4b4/Tff7b72htmlTb4b4b4>

Served by rngit 1.5.2 - Generated in 0.5s